Initial check-in for software m4v_h263 encoder

Change-Id: I4b49fa5c3a5e6e21cfd2419441d98dd784046367
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 49cf647..89bfc1f 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -68,6 +68,7 @@
         libstagefright_avcdec \
         libstagefright_avcenc \
         libstagefright_m4vh263dec \
+        libstagefright_m4vh263enc \
         libstagefright_mp3dec \
         libstagefright_vorbisdec \
         libstagefright_matroska \
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 157897b..7762bf4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -27,6 +27,7 @@
 #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"
@@ -83,6 +84,7 @@
 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,
@@ -97,6 +99,7 @@
         FACTORY_REF(AMRWBEncoder)
         FACTORY_REF(AACEncoder)
         FACTORY_REF(AVCEncoder)
+        FACTORY_REF(M4vH263Encoder)
     };
     for (size_t i = 0;
          i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
@@ -181,10 +184,12 @@
     { 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, "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, "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" },
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..e375250
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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) {
+
+    CHECK(!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..df1aa8b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
@@ -0,0 +1,228 @@
+/* ------------------------------------------------------------------
+ * 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 <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/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_