summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2010-07-12 21:46:25 -0700
committerJames Dong <jdong@google.com>2010-07-15 13:28:21 -0700
commit59f566c4ec3dfc097ad8163523e522280b27e5c3 (patch)
tree6afe2f257d631e487a959e21015152d1d156cb5b
parente957045dcfdc7e08a5d76463b125d2a9e92bc0e8 (diff)
downloadframeworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.zip
frameworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.tar.gz
frameworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.tar.bz2
Initial check-in for software m4v_h263 encoder
Change-Id: I4b49fa5c3a5e6e21cfd2419441d98dd784046367
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/OMXCodec.cpp5
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/Android.mk37
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp359
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/include/cvei.h437
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h454
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp859
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h57
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp693
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp482
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp1283
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct.h191
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h395
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp622
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h103
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp2020
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp967
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h625
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp287
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h43
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp386
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp1965
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp1741
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h228
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp3278
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h207
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h472
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp885
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h96
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp375
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp855
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h130
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h539
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h317
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h1146
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp2799
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h42
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h316
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp581
-rw-r--r--media/libstagefright/include/M4vH263Encoder.h80
40 files changed, 26358 insertions, 0 deletions
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 @@ LOCAL_STATIC_LIBRARIES := \
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(AMRNBEncoder)
FACTORY_CREATE_ENCODER(AMRWBEncoder)
FACTORY_CREATE_ENCODER(AACEncoder)
FACTORY_CREATE_ENCODER(AVCEncoder)
+FACTORY_CREATE_ENCODER(M4vH263Encoder)
static sp<MediaSource> InstantiateSoftwareEncoder(
const char *name, const sp<MediaSource> &source,
@@ -97,6 +99,7 @@ static sp<MediaSource> InstantiateSoftwareEncoder(
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 @@ static const CodecInfo kEncoderInfo[] = {
{ 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_