summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/avc/dec
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-12-10 09:44:29 -0800
committerAndreas Huber <andih@google.com>2009-12-10 14:43:44 -0800
commit609f1a00c96cf5605f4614e7bb6d0487c98969c5 (patch)
tree31aa2b3d1787a2f236b733ab27dff8aff04b3197 /media/libstagefright/codecs/avc/dec
parentdf08a8102aa0721afec6df5db8f5742f5542473c (diff)
downloadframeworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.zip
frameworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.tar.gz
frameworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.tar.bz2
Initial checkin of software AVC video decoder based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/avc/dec')
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp439
-rw-r--r--media/libstagefright/codecs/avc/dec/Android.mk27
-rw-r--r--media/libstagefright/codecs/avc/dec/include/avcdec_api.h200
-rw-r--r--media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h49
-rw-r--r--media/libstagefright/codecs/avc/dec/include/pvavcdecoder_factory.h43
-rw-r--r--media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h48
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp276
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp1036
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h125
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avcdec_int.h88
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avcdec_lib.h555
-rw-r--r--media/libstagefright/codecs/avc/dec/src/header.cpp1391
-rw-r--r--media/libstagefright/codecs/avc/dec/src/itrans.cpp307
-rw-r--r--media/libstagefright/codecs/avc/dec/src/pred_inter.cpp2329
-rw-r--r--media/libstagefright/codecs/avc/dec/src/pred_intra.cpp1786
-rw-r--r--media/libstagefright/codecs/avc/dec/src/residual.cpp523
-rw-r--r--media/libstagefright/codecs/avc/dec/src/slice.cpp772
-rw-r--r--media/libstagefright/codecs/avc/dec/src/vlc.cpp815
18 files changed, 10809 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
new file mode 100644
index 0000000..0fc9622
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AVCDecoder.h"
+
+#include "avcdec_api.h"
+#include "avcdec_int.h"
+
+#include <OMX_Component.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
+ return reinterpret_cast<int32_t>(malloc(size));
+}
+
+static void Free(void *userData, int32_t ptr) {
+ free(reinterpret_cast<void *>(ptr));
+}
+
+AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
+ : mSource(source),
+ mStarted(false),
+ mHandle(new tagAVCHandle),
+ mInputBuffer(NULL),
+ mAnchorTimeUs(0),
+ mNumSamplesOutput(0) {
+ memset(mHandle, 0, sizeof(tagAVCHandle));
+ mHandle->AVCObject = NULL;
+ mHandle->userData = this;
+ mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper;
+ mHandle->CBAVC_FrameBind = BindFrameWrapper;
+ mHandle->CBAVC_FrameUnbind = UnbindFrame;
+ mHandle->CBAVC_Malloc = Malloc;
+ mHandle->CBAVC_Free = Free;
+
+ mFormat = new MetaData;
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ int32_t width, height;
+ CHECK(mSource->getFormat()->findInt32(kKeyWidth, &width));
+ CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height));
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+ mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+ mFormat->setCString(kKeyDecoderComponent, "AVCDecoder");
+}
+
+AVCDecoder::~AVCDecoder() {
+ if (mStarted) {
+ stop();
+ }
+
+ delete mHandle;
+ mHandle = NULL;
+}
+
+status_t AVCDecoder::start(MetaData *) {
+ CHECK(!mStarted);
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (mSource->getFormat()->findData(kKeyAVCC, &type, &data, &size)) {
+ // Parse the AVCDecoderConfigurationRecord
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ(ptr[0], 1); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+ }
+
+ sp<MetaData> params = new MetaData;
+ params->setInt32(kKeyWantsNALFragments, true);
+ mSource->start(params.get());
+
+ mAnchorTimeUs = 0;
+ mNumSamplesOutput = 0;
+ mStarted = true;
+
+ return OK;
+}
+
+void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
+ MediaBuffer *buffer = new MediaBuffer(size);
+ memcpy(buffer->data(), data, size);
+ buffer->set_range(0, size);
+
+ mCodecSpecificData.push(buffer);
+}
+
+status_t AVCDecoder::stop() {
+ CHECK(mStarted);
+
+ for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
+ (*mCodecSpecificData.editItemAt(i)).release();
+ }
+ mCodecSpecificData.clear();
+
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ mSource->stop();
+
+ releaseFrames();
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> AVCDecoder::getFormat() {
+ return mFormat;
+}
+
+status_t AVCDecoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ if (mInputBuffer == NULL) {
+ LOGV("fetching new input buffer.");
+
+ if (!mCodecSpecificData.isEmpty()) {
+ mInputBuffer = mCodecSpecificData.editItemAt(0);
+ mCodecSpecificData.removeAt(0);
+ } else {
+ for (;;) {
+ status_t err = mSource->read(&mInputBuffer);
+ if (err != OK) {
+ return err;
+ }
+
+ if (mInputBuffer->range_length() > 0) {
+ break;
+ }
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+ }
+ }
+
+ const uint8_t *inPtr =
+ (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
+
+ int nalType;
+ int nalRefIdc;
+ AVCDec_Status res =
+ PVAVCDecGetNALType(
+ const_cast<uint8_t *>(inPtr), mInputBuffer->range_length(),
+ &nalType, &nalRefIdc);
+
+ if (res != AVCDEC_SUCCESS) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ return UNKNOWN_ERROR;
+ }
+
+ switch (nalType) {
+ case AVC_NALTYPE_SPS:
+ {
+ res = PVAVCDecSeqParamSet(
+ mHandle, const_cast<uint8_t *>(inPtr),
+ mInputBuffer->range_length());
+
+ if (res != AVCDEC_SUCCESS) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ return UNKNOWN_ERROR;
+ }
+
+ AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
+
+ int32_t width =
+ (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
+
+ int32_t height =
+ (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
+
+ int32_t crop_left, crop_right, crop_top, crop_bottom;
+ if (pDecVid->seqParams[0]->frame_cropping_flag)
+ {
+ crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
+ crop_right =
+ width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
+
+ if (pDecVid->seqParams[0]->frame_mbs_only_flag)
+ {
+ crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
+ crop_bottom =
+ height -
+ (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
+ }
+ else
+ {
+ crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
+ crop_bottom =
+ height -
+ (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
+ }
+ } else {
+ crop_bottom = height - 1;
+ crop_right = width - 1;
+ crop_top = crop_left = 0;
+ }
+
+ mFormat->setInt32(kKeyWidth, crop_right - crop_left + 1);
+ mFormat->setInt32(kKeyHeight, crop_bottom - crop_top + 1);
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ return INFO_FORMAT_CHANGED;
+ }
+
+ case AVC_NALTYPE_PPS:
+ {
+ res = PVAVCDecPicParamSet(
+ mHandle, const_cast<uint8_t *>(inPtr),
+ mInputBuffer->range_length());
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ if (res != AVCDEC_SUCCESS) {
+ return UNKNOWN_ERROR;
+ }
+
+ *out = new MediaBuffer(0);
+
+ return OK;
+ }
+
+ case AVC_NALTYPE_SLICE:
+ case AVC_NALTYPE_IDR:
+ {
+ res = PVAVCDecodeSlice(
+ mHandle, const_cast<uint8_t *>(inPtr),
+ mInputBuffer->range_length());
+
+ if (res == AVCDEC_PICTURE_OUTPUT_READY) {
+ int32_t index;
+ int32_t Release;
+ AVCFrameIO Output;
+ Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
+ CHECK_EQ(PVAVCDecGetOutput(
+ mHandle, &index, &Release, &Output),
+ AVCDEC_SUCCESS);
+
+ CHECK(index >= 0);
+ CHECK(index < (int32_t)mFrames.size());
+
+ *out = mFrames.editItemAt(index);
+ (*out)->set_range(0, (*out)->size());
+ (*out)->add_ref();
+
+ // Do _not_ release input buffer yet.
+
+ return OK;
+ }
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ if (res == AVCDEC_PICTURE_READY) {
+ *out = new MediaBuffer(0);
+
+ return OK;
+ } else {
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ case AVC_NALTYPE_SEI:
+ {
+ res = PVAVCDecodeSlice(
+ mHandle, const_cast<uint8_t *>(inPtr),
+ mInputBuffer->range_length());
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ if (res != AVCDEC_SUCCESS) {
+ return UNKNOWN_ERROR;
+ }
+
+ *out = new MediaBuffer(0);
+
+ return OK;
+ }
+
+ default:
+ {
+ LOGE("Should not be here, unknown nalType %d", nalType);
+ CHECK(!"Should not be here");
+ break;
+ }
+ }
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ return UNKNOWN_ERROR;
+}
+
+// static
+int32_t AVCDecoder::ActivateSPSWrapper(
+ void *userData, unsigned int sizeInMbs, unsigned int numBuffers) {
+ return static_cast<AVCDecoder *>(userData)->activateSPS(sizeInMbs, numBuffers);
+}
+
+// static
+int32_t AVCDecoder::BindFrameWrapper(
+ void *userData, int32_t index, uint8_t **yuv) {
+ return static_cast<AVCDecoder *>(userData)->bindFrame(index, yuv);
+}
+
+// static
+void AVCDecoder::UnbindFrame(void *userData, int32_t index) {
+}
+
+int32_t AVCDecoder::activateSPS(
+ unsigned int sizeInMbs, unsigned int numBuffers) {
+ CHECK(mFrames.isEmpty());
+
+ size_t frameSize = (sizeInMbs << 7) * 3;
+ for (unsigned int i = 0; i < numBuffers; ++i) {
+ MediaBuffer *buffer = new MediaBuffer(frameSize);
+ buffer->setObserver(this);
+
+ mFrames.push(buffer);
+ }
+
+ return 1;
+}
+
+int32_t AVCDecoder::bindFrame(int32_t index, uint8_t **yuv) {
+ CHECK(index >= 0);
+ CHECK(index < (int32_t)mFrames.size());
+
+ CHECK(mInputBuffer != NULL);
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ mFrames[index]->meta_data()->setInt64(kKeyTime, timeUs);
+
+ *yuv = (uint8_t *)mFrames[index]->data();
+
+ return 1;
+}
+
+void AVCDecoder::releaseFrames() {
+ for (size_t i = 0; i < mFrames.size(); ++i) {
+ MediaBuffer *buffer = mFrames.editItemAt(i);
+
+ buffer->setObserver(NULL);
+ buffer->release();
+ }
+ mFrames.clear();
+}
+
+void AVCDecoder::signalBufferReturned(MediaBuffer *buffer) {
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/avc/dec/Android.mk b/media/libstagefright/codecs/avc/dec/Android.mk
new file mode 100644
index 0000000..2a1c8e0
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AVCDecoder.cpp \
+ src/avcdec_api.cpp \
+ src/avc_bitstream.cpp \
+ src/header.cpp \
+ src/itrans.cpp \
+ src/pred_inter.cpp \
+ src/pred_intra.cpp \
+ src/residual.cpp \
+ src/slice.cpp \
+ src/vlc.cpp
+
+LOCAL_MODULE := libstagefright_avcdec
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../common/include \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+
+LOCAL_CFLAGS := -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/dec/include/avcdec_api.h b/media/libstagefright/codecs/avc/dec/include/avcdec_api.h
new file mode 100644
index 0000000..f6a14b7
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/include/avcdec_api.h
@@ -0,0 +1,200 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC decoder library
+and necessary type defitionitions and enumerations.
+@publishedAll
+*/
+
+#ifndef _AVCDEC_API_H_
+#define _AVCDEC_API_H_
+
+#include "avcapi_common.h"
+
+/**
+ This enumeration is used for the status returned from the library interface.
+*/
+typedef enum
+{
+ /**
+ The followings are fail with details. Their values are negative.
+ */
+ AVCDEC_NO_DATA = -4,
+ AVCDEC_PACKET_LOSS = -3,
+ /**
+ Fail information
+ */
+ AVCDEC_NO_BUFFER = -2, /* no output picture buffer available */
+ AVCDEC_MEMORY_FAIL = -1, /* memory allocation failed */
+ AVCDEC_FAIL = 0,
+ /**
+ Generic success value
+ */
+ AVCDEC_SUCCESS = 1,
+ AVCDEC_PICTURE_OUTPUT_READY = 2,
+ AVCDEC_PICTURE_READY = 3,
+
+ /**
+ The followings are success with warnings. Their values are positive integers.
+ */
+ AVCDEC_NO_NEXT_SC = 4,
+ AVCDEC_REDUNDANT_FRAME = 5,
+ AVCDEC_CONCEALED_FRAME = 6 /* detect and conceal the error */
+} AVCDec_Status;
+
+
+/**
+This structure contains sequence parameters information.
+*/
+typedef struct tagAVCDecSPSInfo
+{
+ int FrameWidth;
+ int FrameHeight;
+ uint frame_only_flag;
+ int frame_crop_left;
+ int frame_crop_right;
+ int frame_crop_top;
+ int frame_crop_bottom;
+
+} AVCDecSPSInfo;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /** THE FOLLOWINGS ARE APIS */
+ /**
+ This function parses one NAL unit from byte stream format input according to Annex B.
+ \param "bitstream" "Pointer to the bitstream buffer."
+ \param "nal_unit" "Point to pointer and the location of the start of the first NAL unit
+ found in bitstream."
+ \param "size" "As input, the pointer to the size of bitstream in bytes. As output,
+ the value is changed to be the size of the found NAL unit."
+ \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL if no first start code is found, AVCDEC_NO_NEX_SC if
+ the first start code is found, but the second start code is missing (potential partial NAL)."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit, int *size);
+
+ /**
+ This function sniffs the nal_unit_type such that users can call corresponding APIs.
+ \param "bitstream" "Pointer to the beginning of a NAL unit (start with forbidden_zero_bit, etc.)."
+ \param "size" "size of the bitstream (NumBytesInNALunit + 1)."
+ \param "nal_unit_type" "Pointer to the return value of nal unit type."
+ \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL otherwise."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetNALType(uint8 *bitstream, int size, int *nal_type, int *nal_ref_idc);
+
+ /**
+ This function decodes the sequence parameters set, initializes related parameters and
+ allocates memory (reference frames list), must also be compliant with Annex A.
+ It is equivalent to decode VOL header of MPEG4.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "nal_unit" "Pointer to the buffer containing single NAL unit.
+ The content will change due to EBSP-to-RBSP conversion."
+ \param "nal_size" "size of the bitstream NumBytesInNALunit."
+ \return "AVCDEC_SUCCESS if success,
+ AVCDEC_FAIL if profile and level is not supported,
+ AVCDEC_MEMORY_FAIL if memory allocations return null."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecSeqParamSet(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
+
+ /**
+ This function returns sequence parameters such as dimension and field flag of the most recently
+ decoded SPS. More can be added later or grouped together into a structure. This API can be called
+ after PVAVCInitSequence. If no sequence parameter has been decoded yet, it will return AVCDEC_FAIL.
+
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "seqInfo" "Pointer to the AVCDecSeqParamInfo structure."
+ \return "AVCDEC_SUCCESS if success and AVCDEC_FAIL if fail."
+ \note "This API can be combined with PVAVCInitSequence if wanted to be consistent with m4vdec lib."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetSeqInfo(AVCHandle *avcHandle, AVCDecSPSInfo *seqInfo);
+
+ /**
+ This function decodes the picture parameters set and initializes related parameters. Note thate
+ the PPS may not be present for every picture.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "nal_unit" "Pointer to the buffer containing single NAL unit.
+ The content will change due to EBSP-to-RBSP conversion."
+ \param "nal_size" "size of the bitstream NumBytesInNALunit."
+ \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL if profile and level is not supported."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecPicParamSet(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
+
+ /**
+ This function decodes one NAL unit of bitstream. The type of nal unit is one of the
+ followings, 1, 5. (for now, no data partitioning, type 2,3,4).
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "nal_unit" "Pointer to the buffer containing a single or partial NAL unit.
+ The content will change due to EBSP-to-RBSP conversion."
+ \param "buf_size" "Size of the buffer (less than or equal nal_size)."
+ \param "nal_size" "size of the current NAL unit NumBytesInNALunit."
+ \return "AVCDEC_PICTURE_READY for success and an output is ready,
+ AVCDEC_SUCCESS for success but no output is ready,
+ AVCDEC_PACKET_LOSS is GetData returns AVCDEC_PACKET_LOSS,
+ AVCDEC_FAIL if syntax error is detected,
+ AVCDEC_MEMORY_FAIL if memory is corrupted.
+ AVCDEC_NO_PICTURE if no frame memory to write to (users need to get output and/or return picture).
+ AVCDEC_REDUNDANT_PICTURE if error has been detected in the primary picture and redundant picture is available,
+ AVCDEC_CONCEALED_PICTURE if error has been detected and decoder has concealed it."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecSEI(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
+
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecodeSlice(AVCHandle *avcHandle, uint8 *buffer, int buf_size);
+
+ /**
+ Check the availability of the decoded picture in decoding order (frame_num).
+ The AVCFrameIO also provide displaying order information such that the application
+ can re-order the frame for display. A picture can be retrieved only once.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "output" "Pointer to the AVCOutput structure. Note that decoder library will
+ not re-used the pixel memory in this structure until it has been returned
+ thru PVAVCReleaseOutput API."
+ \return "AVCDEC_SUCCESS for success, AVCDEC_FAIL if no picture is available to be displayed,
+ AVCDEC_PICTURE_READY if there is another picture to be displayed."
+ */
+ OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetOutput(AVCHandle *avcHandle, int *indx, int *release_flag, AVCFrameIO *output);
+
+ /**
+ This function resets the decoder and expects to see the next IDR slice.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ */
+ OSCL_IMPORT_REF void PVAVCDecReset(AVCHandle *avcHandle);
+
+ /**
+ This function performs clean up operation including memory deallocation.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ */
+ OSCL_IMPORT_REF void PVAVCCleanUpDecoder(AVCHandle *avcHandle);
+//AVCDec_Status EBSPtoRBSP(uint8 *nal_unit,int *size);
+
+
+
+ /** CALLBACK FUNCTION TO BE IMPLEMENTED BY APPLICATION */
+ /** In AVCHandle structure, userData is a pointer to an object with the following
+ member functions.
+ */
+ AVCDec_Status CBAVCDec_GetData(uint32 *userData, unsigned char **buffer, unsigned int *size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AVCDEC_API_H_ */
+
diff --git a/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h b/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h
new file mode 100644
index 0000000..6b196de
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h
@@ -0,0 +1,49 @@
+/* ------------------------------------------------------------------
+ * 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 PVAVCDECODER_H_INCLUDED
+#define PVAVCDECODER_H_INCLUDED
+
+#ifndef PVAVCDECODERINTERFACE_H_INCLUDED
+#include "pvavcdecoderinterface.h"
+#endif
+
+// AVC video decoder
+class PVAVCDecoder : public PVAVCDecoderInterface
+{
+ public:
+ virtual ~PVAVCDecoder();
+ static PVAVCDecoder* New(void);
+ virtual bool InitAVCDecoder(FunctionType_SPS, FunctionType_Alloc, FunctionType_Unbind,
+ FunctionType_Malloc, FunctionType_Free, void *);
+ virtual void CleanUpAVCDecoder(void);
+ virtual void ResetAVCDecoder(void);
+ virtual int32 DecodeSPS(uint8 *bitstream, int32 buffer_size);
+ virtual int32 DecodePPS(uint8 *bitstream, int32 buffer_size);
+ virtual int32 DecodeAVCSlice(uint8 *bitstream, int32 *buffer_size);
+ virtual bool GetDecOutput(int *indx, int *release);
+ virtual void GetVideoDimensions(int32 *width, int32 *height, int32 *top, int32 *left, int32 *bottom, int32 *right);
+ int AVC_Malloc(int32 size, int attribute);
+ void AVC_Free(int mem);
+
+ private:
+ PVAVCDecoder();
+ bool Construct(void);
+ void *iAVCHandle;
+};
+
+#endif
diff --git a/media/libstagefright/codecs/avc/dec/include/pvavcdecoder_factory.h b/media/libstagefright/codecs/avc/dec/include/pvavcdecoder_factory.h
new file mode 100644
index 0000000..440f8ec
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/include/pvavcdecoder_factory.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.
+ * -------------------------------------------------------------------
+ */
+#ifndef PVAVCDECODER_FACTORY_H_INCLUDED
+#define PVAVCDECODER_FACTORY_H_INCLUDED
+
+class PVAVCDecoderInterface;
+
+class PVAVCDecoderFactory
+{
+ public:
+ /**
+ * Creates an instance of a PVAVCDecoder. If the creation fails, this function will leave.
+ *
+ * @returns A pointer to an instance of PVAVCDecoder as PVAVCDecoderInterface reference or leaves if instantiation fails
+ **/
+ OSCL_IMPORT_REF static PVAVCDecoderInterface* CreatePVAVCDecoder(void);
+
+ /**
+ * Deletes an instance of PVAVCDecoder and reclaims all allocated resources.
+ *
+ * @param aVideoDec The PVAVCDecoder instance to be deleted
+ * @returns A status code indicating success or failure of deletion
+ **/
+ OSCL_IMPORT_REF static bool DeletePVAVCDecoder(PVAVCDecoderInterface* aVideoDec);
+};
+
+#endif
+
diff --git a/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h b/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h
new file mode 100644
index 0000000..027212d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h
@@ -0,0 +1,48 @@
+/* ------------------------------------------------------------------
+ * 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 PVAVCDECODERINTERFACE_H_INCLUDED
+#define PVAVCDECODERINTERFACE_H_INCLUDED
+
+typedef void (*FunctionType_Unbind)(void *, int);
+typedef int (*FunctionType_Alloc)(void *, int, uint8 **);
+typedef int (*FunctionType_SPS)(void *, uint, uint);
+typedef int (*FunctionType_Malloc)(void *, int32, int);
+typedef void(*FunctionType_Free)(void *, int);
+
+
+// PVAVCDecoderInterface pure virtual interface class
+class PVAVCDecoderInterface
+{
+ public:
+ virtual ~PVAVCDecoderInterface() {};
+ virtual bool InitAVCDecoder(FunctionType_SPS, FunctionType_Alloc, FunctionType_Unbind,
+ FunctionType_Malloc, FunctionType_Free, void *) = 0;
+ virtual void CleanUpAVCDecoder(void) = 0;
+ virtual void ResetAVCDecoder(void) = 0;
+ virtual int32 DecodeSPS(uint8 *bitstream, int32 buffer_size) = 0;
+ virtual int32 DecodePPS(uint8 *bitstream, int32 buffer_size) = 0;
+ virtual int32 DecodeAVCSlice(uint8 *bitstream, int32 *buffer_size) = 0;
+ virtual bool GetDecOutput(int *indx, int *release) = 0;
+ virtual void GetVideoDimensions(int32 *width, int32 *height, int32 *top, int32 *left, int32 *bottom, int32 *right) = 0;
+// virtual int AVC_Malloc(int32 size, int attribute);
+// virtual void AVC_Free(int mem);
+};
+
+#endif // PVAVCDECODERINTERFACE_H_INCLUDED
+
+
diff --git a/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp b/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp
new file mode 100644
index 0000000..270b664
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp
@@ -0,0 +1,276 @@
+/* ------------------------------------------------------------------
+ * 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 "avcdec_bitstream.h"
+
+/* Swapping may not be needed anymore since we read one byte at a time and perform
+EBSP to RBSP conversion in bitstream. */
+#ifdef LITTLE_ENDIAN
+#if (WORD_SIZE==32) /* this can be replaced with assembly instructions */
+#define SWAP_BYTES(x) ((((x)&0xFF)<<24) | (((x)&0xFF00)<<8) | (((x)&0xFF0000)>>8) | (((x)&0xFF000000)>>24))
+#else /* for 16-bit */
+#define SWAP_BYTES(x) ((((x)&0xFF)<<8) | (((x)&0xFF00)>>8))
+#endif
+#else
+#define SWAP_BYTES(x) (x)
+#endif
+
+
+/* array for trailing bit pattern as function of number of bits */
+/* the first one is unused. */
+const static uint8 trailing_bits[9] = {0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
+
+/* ======================================================================== */
+/* Function : BitstreamInit() */
+/* Date : 11/4/2003 */
+/* Purpose : Populate bitstream structure with bitstream buffer and size */
+/* it also initializes internal data */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if failed. */
+/* Modified : */
+/* ======================================================================== */
+/* |--------|--------|----~~~~~-----|---------|---------|---------|
+ ^ ^read_pos ^data_end_pos
+ bitstreamBuffer <--------->
+ current_word
+
+ |xxxxxxxxxxxxx----| = current_word 32 or 16 bits
+ <------------>
+ bit_left
+ ======================================================================== */
+
+
+/* ======================================================================== */
+/* Function : BitstreamNextWord() */
+/* Date : 12/4/2003 */
+/* Purpose : Read up to machine word. */
+/* In/out : */
+/* Return : Next word with emulation prevention code removed. Everything
+ in the bitstream structure got modified except current_word */
+/* Modified : */
+/* ======================================================================== */
+
+AVCDec_Status BitstreamInit(AVCDecBitstream *stream, uint8 *buffer, int size)
+{
+ EBSPtoRBSP(buffer, &size);
+
+ stream->incnt = 0;
+ stream->incnt_next = 0;
+ stream->bitcnt = 0;
+ stream->curr_word = stream->next_word = 0;
+ stream->read_pos = 0;
+
+ stream->bitstreamBuffer = buffer;
+
+ stream->data_end_pos = size;
+
+ stream->nal_size = size;
+
+ return AVCDEC_SUCCESS;
+}
+/* ======================================================================== */
+/* Function : AVC_BitstreamFillCache() */
+/* Date : 1/1/2005 */
+/* Purpose : Read up to machine word. */
+/* In/out : */
+/* Return : Read in 4 bytes of input data */
+/* Modified : */
+/* ======================================================================== */
+
+AVCDec_Status AVC_BitstreamFillCache(AVCDecBitstream *stream)
+{
+ uint8 *bitstreamBuffer = stream->bitstreamBuffer;
+ uint8 *v;
+ int num_bits, i;
+
+ stream->curr_word |= (stream->next_word >> stream->incnt); // stream->incnt cannot be 32
+ stream->next_word <<= (31 - stream->incnt);
+ stream->next_word <<= 1;
+ num_bits = stream->incnt_next + stream->incnt;
+ if (num_bits >= 32)
+ {
+ stream->incnt_next -= (32 - stream->incnt);
+ stream->incnt = 32;
+ return AVCDEC_SUCCESS;
+ }
+ /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */
+ v = bitstreamBuffer + stream->read_pos;
+
+ if (stream->read_pos > stream->data_end_pos - 4)
+ {
+ if (stream->data_end_pos <= stream->read_pos)
+ {
+ stream->incnt = num_bits;
+ stream->incnt_next = 0;
+ return AVCDEC_SUCCESS;
+ }
+
+ stream->next_word = 0;
+
+ for (i = 0; i < stream->data_end_pos - stream->read_pos; i++)
+ {
+ stream->next_word |= (v[i] << ((3 - i) << 3));
+ }
+
+ stream->read_pos = stream->data_end_pos;
+ stream->curr_word |= (stream->next_word >> num_bits); // this is safe
+
+ stream->next_word <<= (31 - num_bits);
+ stream->next_word <<= 1;
+ num_bits = i << 3;
+ stream->incnt += stream->incnt_next;
+ stream->incnt_next = num_bits - (32 - stream->incnt);
+ if (stream->incnt_next < 0)
+ {
+ stream->incnt += num_bits;
+ stream->incnt_next = 0;
+ }
+ else
+ {
+ stream->incnt = 32;
+ }
+ return AVCDEC_SUCCESS;
+ }
+
+ stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
+ stream->read_pos += 4;
+
+ stream->curr_word |= (stream->next_word >> num_bits); // this is safe
+ stream->next_word <<= (31 - num_bits);
+ stream->next_word <<= 1;
+ stream->incnt_next += stream->incnt;
+ stream->incnt = 32;
+ return AVCDEC_SUCCESS;
+
+}
+/* ======================================================================== */
+/* Function : BitstreamReadBits() */
+/* Date : 11/4/2003 */
+/* Purpose : Read up to machine word. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */
+/* is greater than the word-size, AVCDEC_PACKET_LOSS or */
+/* AVCDEC_NO_DATA if callback to get data fails. */
+/* Modified : */
+/* ======================================================================== */
+AVCDec_Status BitstreamReadBits(AVCDecBitstream *stream, int nBits, uint *code)
+{
+ if (stream->incnt < nBits)
+ {
+ /* frame-based decoding */
+ AVC_BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> (32 - nBits);
+ BitstreamFlushBits(stream, nBits);
+ return AVCDEC_SUCCESS;
+}
+
+
+
+/* ======================================================================== */
+/* Function : BitstreamShowBits() */
+/* Date : 11/4/2003 */
+/* Purpose : Show up to machine word without advancing the pointer. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */
+/* is greater than the word-size, AVCDEC_NO_DATA if it needs */
+/* to callback to get data. */
+/* Modified : */
+/* ======================================================================== */
+AVCDec_Status BitstreamShowBits(AVCDecBitstream *stream, int nBits, uint *code)
+{
+ if (stream->incnt < nBits)
+ {
+ /* frame-based decoding */
+ AVC_BitstreamFillCache(stream);
+ }
+
+ *code = stream->curr_word >> (32 - nBits);
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamRead1Bit() */
+/* Date : 11/4/2003 */
+/* Purpose : Read 1 bit from the bitstream. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */
+/* is greater than the word-size, AVCDEC_PACKET_LOSS or */
+/* AVCDEC_NO_DATA if callback to get data fails. */
+/* Modified : */
+/* ======================================================================== */
+
+AVCDec_Status BitstreamRead1Bit(AVCDecBitstream *stream, uint *code)
+{
+ if (stream->incnt < 1)
+ {
+ /* frame-based decoding */
+ AVC_BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> 31;
+ BitstreamFlushBits(stream, 1);
+ return AVCDEC_SUCCESS;
+}
+
+
+
+AVCDec_Status BitstreamByteAlign(AVCDecBitstream *stream)
+{
+ uint n_stuffed;
+
+ n_stuffed = (8 - (stream->bitcnt & 0x7)) & 0x7; /* 07/05/01 */
+
+ stream->bitcnt += n_stuffed;
+ stream->incnt -= n_stuffed;
+
+ if (stream->incnt < 0)
+ {
+ stream->bitcnt += stream->incnt;
+ stream->incnt = 0;
+ }
+ stream->curr_word <<= n_stuffed;
+ return AVCDEC_SUCCESS;
+}
+
+/* check whether there are more RBSP data. */
+/* ignore the emulation prevention code, assume it has been taken out. */
+bool more_rbsp_data(AVCDecBitstream *stream)
+{
+ int total_bit_left;
+ uint code;
+
+ if (stream->read_pos >= stream->nal_size)
+ {
+ total_bit_left = stream->incnt_next + stream->incnt;
+ if (total_bit_left <= 0)
+ {
+ return FALSE;
+ }
+ else if (total_bit_left <= 8)
+ {
+ BitstreamShowBits(stream, total_bit_left, &code);
+ if (code == trailing_bits[total_bit_left])
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp b/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
new file mode 100644
index 0000000..0a75f17
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
@@ -0,0 +1,1036 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC decoder library.
+@publishedAll
+*/
+
+#include <string.h>
+
+#include "avcdec_api.h"
+#include "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+
+/* ======================================================================== */
+/* Function : EBSPtoRBSP() */
+/* Date : 11/4/2003 */
+/* Purpose : Convert EBSP to RBSP and overwrite it. */
+/* Assuming that forbidden_zero, nal_ref_idc and nal_unit_type */
+/* (first byte), has been taken out of the nal_unit. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+/**
+@pseudocode "
+ NumBytesInRBSP = 0;
+ for(i=0:i< *size; i++){
+ if(i+2 < *size && next_bits(24)==0x000003){
+ rbsp_byte[NumBytesInRBSP++];
+ rbsp_byte[NumBytesInRBSP++];
+ i+=2;
+ emulation_prevention_three_byte (0x03)
+ }
+ else
+ rbsp_byte[NumBytesInRBSP++];
+ }"
+*/
+AVCDec_Status EBSPtoRBSP(uint8 *nal_unit, int *size)
+{
+ int i, j;
+ int count = 0;
+
+ /* This code is based on EBSPtoRBSP of JM */
+ j = 0;
+
+ for (i = 0; i < *size; i++)
+ {
+ if (count == 2 && nal_unit[i] == 0x03)
+ {
+ i++;
+ count = 0;
+ }
+ nal_unit[j] = nal_unit[i];
+ if (nal_unit[i] == 0x00)
+ count++;
+ else
+ count = 0;
+ j++;
+ }
+
+ *size = j;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCAnnexBGetNALUnit() */
+/* Date : 11/3/2003 */
+/* Purpose : Parse a NAL from byte stream format. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+/**
+@pseudocode "
+ byte_stream_nal_unit(NumBytesInNalunit){
+ while(next_bits(24) != 0x000001)
+ zero_byte
+ if(more_data_in_byte_stream()){
+ start_code_prefix_one_3bytes // equal 0x000001
+ nal_unit(NumBytesInNALunit)
+ }
+ }"
+*/
+OSCL_EXPORT_REF AVCDec_Status PVAVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit,
+ int *size)
+{
+ int i, j, FoundStartCode = 0;
+ int end;
+
+ i = 0;
+ while (bitstream[i] == 0 && i < *size)
+ {
+ i++;
+ }
+ if (i >= *size)
+ {
+ *nal_unit = bitstream;
+ return AVCDEC_FAIL; /* cannot find any start_code_prefix. */
+ }
+ else if (bitstream[i] != 0x1)
+ {
+ i = -1; /* start_code_prefix is not at the beginning, continue */
+ }
+
+ i++;
+ *nal_unit = bitstream + i; /* point to the beginning of the NAL unit */
+
+ j = end = i;
+ while (!FoundStartCode)
+ {
+ while ((j + 1 < *size) && (bitstream[j] != 0 || bitstream[j+1] != 0)) /* see 2 consecutive zero bytes */
+ {
+ j++;
+ }
+ end = j; /* stop and check for start code */
+ while (j + 2 < *size && bitstream[j+2] == 0) /* keep reading for zero byte */
+ {
+ j++;
+ }
+ if (j + 2 >= *size)
+ {
+ *size -= i;
+ return AVCDEC_NO_NEXT_SC; /* cannot find the second start_code_prefix */
+ }
+ if (bitstream[j+2] == 0x1)
+ {
+ FoundStartCode = 1;
+ }
+ else
+ {
+ /* could be emulation code 0x3 */
+ j += 2; /* continue the search */
+ }
+ }
+
+ *size = end - i;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCGetNALType() */
+/* Date : 11/4/2003 */
+/* Purpose : Sniff NAL type from the bitstream */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetNALType(uint8 *bitstream, int size,
+ int *nal_type, int *nal_ref_idc)
+{
+ int forbidden_zero_bit;
+ if (size > 0)
+ {
+ forbidden_zero_bit = bitstream[0] >> 7;
+ if (forbidden_zero_bit != 0)
+ return AVCDEC_FAIL;
+ *nal_ref_idc = (bitstream[0] & 0x60) >> 5;
+ *nal_type = bitstream[0] & 0x1F;
+ return AVCDEC_SUCCESS;
+ }
+
+ return AVCDEC_FAIL;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecSeqParamSet() */
+/* Date : 11/4/2003 */
+/* Purpose : Initialize sequence, memory allocation if necessary. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecSeqParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ AVCDec_Status status;
+ AVCDecObject *decvid;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+ void *userData = avcHandle->userData;
+ bool first_seq = FALSE;
+ int i;
+
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCDecSeqParamSet", -1, -1);
+
+ if (avcHandle->AVCObject == NULL)
+ {
+ first_seq = TRUE;
+
+ //avcHandle->memory_usage = 0;
+ /* allocate AVCDecObject */
+ avcHandle->AVCObject = (void*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecObject), 0/*DEFAULT_ATTR*/);
+ if (avcHandle->AVCObject == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ decvid = (AVCDecObject*) avcHandle->AVCObject;
+
+ memset(decvid, 0, sizeof(AVCDecObject));
+
+ decvid->common = (AVCCommonObj*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCCommonObj), 0);
+ if (decvid->common == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ video = decvid->common;
+ memset(video, 0, sizeof(AVCCommonObj));
+
+ video->seq_parameter_set_id = 9999; /* set it to some illegal value */
+
+ decvid->bitstream = (AVCDecBitstream *) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecBitstream), 1/*DEFAULT_ATTR*/);
+ if (decvid->bitstream == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ decvid->bitstream->userData = avcHandle->userData; /* callback for more data */
+ decvid->avcHandle = avcHandle;
+ decvid->debugEnable = avcHandle->debugEnable;
+ }
+
+ decvid = (AVCDecObject*) avcHandle->AVCObject;
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+
+ /* check if we can reuse the memory without re-allocating it. */
+ /* always check if(first_seq==TRUE) */
+
+ /* Conversion from EBSP to RBSP */
+ video->forbidden_bit = nal_unit[0] >> 7;
+ if (video->forbidden_bit) return AVCDEC_FAIL;
+ video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
+
+ if (video->nal_unit_type != AVC_NALTYPE_SPS) /* not a SPS NAL */
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* Initialize bitstream structure*/
+ BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
+
+ /* if first_seq == TRUE, allocate the following memory */
+ if (first_seq == TRUE)
+ {
+ video->currSeqParams = NULL; /* initialize it to NULL */
+ video->currPicParams = NULL;
+
+ /* There are 32 pointers to sequence param set, seqParams.
+ There are 255 pointers to picture param set, picParams.*/
+ for (i = 0; i < 32; i++)
+ decvid->seqParams[i] = NULL;
+
+ for (i = 0; i < 256; i++)
+ decvid->picParams[i] = NULL;
+
+ video->MbToSliceGroupMap = NULL;
+
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ video->newPic = TRUE;
+ video->newSlice = TRUE;
+ video->currPic = NULL;
+ video->currFS = NULL;
+ video->prevRefPic = NULL;
+
+ video->mbNum = 0; // MC_Conceal
+ /* Allocate sliceHdr. */
+
+ video->sliceHdr = (AVCSliceHeader*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSliceHeader), 5/*DEFAULT_ATTR*/);
+ if (video->sliceHdr == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ video->decPicBuf = (AVCDecPicBuffer*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecPicBuffer), 3/*DEFAULT_ATTR*/);
+ if (video->decPicBuf == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+ memset(video->decPicBuf, 0, sizeof(AVCDecPicBuffer));
+ }
+
+ /* Decode SPS, allocate video->seqParams[i] and assign video->currSeqParams */
+ status = DecodeSPS(decvid, bitstream);
+
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecGetSeqInfo() */
+/* Date : 11/4/2003 */
+/* Purpose : Get sequence parameter info. after SPS NAL is decoded. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* 12/20/03: change input argument, use structure instead. */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetSeqInfo(AVCHandle *avcHandle, AVCDecSPSInfo *seqInfo)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ int PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs;
+
+ if (decvid == NULL || decvid->seqParams[0] == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+
+ PicWidthInMbs = decvid->seqParams[0]->pic_width_in_mbs_minus1 + 1;
+ PicHeightInMapUnits = decvid->seqParams[0]->pic_height_in_map_units_minus1 + 1 ;
+ FrameHeightInMbs = (2 - decvid->seqParams[0]->frame_mbs_only_flag) * PicHeightInMapUnits ;
+
+ seqInfo->FrameWidth = PicWidthInMbs << 4;
+ seqInfo->FrameHeight = FrameHeightInMbs << 4;
+
+ seqInfo->frame_only_flag = decvid->seqParams[0]->frame_mbs_only_flag;
+
+ if (decvid->seqParams[0]->frame_cropping_flag)
+ {
+ seqInfo->frame_crop_left = 2 * decvid->seqParams[0]->frame_crop_left_offset;
+ seqInfo->frame_crop_right = seqInfo->FrameWidth - (2 * decvid->seqParams[0]->frame_crop_right_offset + 1);
+
+ if (seqInfo->frame_only_flag)
+ {
+ seqInfo->frame_crop_top = 2 * decvid->seqParams[0]->frame_crop_top_offset;
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (2 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
+ /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
+ such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/2, respectively. */
+ }
+ else
+ {
+ seqInfo->frame_crop_top = 4 * decvid->seqParams[0]->frame_crop_top_offset;
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (4 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
+ /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
+ such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/4, respectively. */
+ }
+ }
+ else /* no cropping flag, just give the first and last pixel */
+ {
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - 1;
+ seqInfo->frame_crop_right = seqInfo->FrameWidth - 1;
+ seqInfo->frame_crop_top = seqInfo->frame_crop_left = 0;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecPicParamSet() */
+/* Date : 11/4/2003 */
+/* Purpose : Initialize picture */
+/* create reference picture list. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+/**
+Since PPS doesn't contain much data, most of the picture initialization will
+be done after decoding the slice header in PVAVCDecodeSlice. */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecPicParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ AVCDec_Status status;
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+ /* 1. Convert EBSP to RBSP. Create bitstream structure */
+ video->forbidden_bit = nal_unit[0] >> 7;
+ video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
+
+ if (video->nal_unit_type != AVC_NALTYPE_PPS) /* not a PPS NAL */
+ {
+ return AVCDEC_FAIL;
+ }
+
+
+ /* 2. Initialize bitstream structure*/
+ BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
+
+ /* 2. Decode pic_parameter_set_rbsp syntax. Allocate video->picParams[i] and assign to currPicParams */
+ status = DecodePPS(decvid, video, bitstream);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+
+ video->SliceGroupChangeRate = video->currPicParams->slice_group_change_rate_minus1 + 1 ;
+
+ return AVCDEC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecSEI(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(nal_unit);
+ OSCL_UNUSED_ARG(nal_size);
+
+ return AVCDEC_SUCCESS;
+}
+/* ======================================================================== */
+/* Function : PVAVCDecodeSlice() */
+/* Date : 11/4/2003 */
+/* Purpose : Decode one NAL unit. */
+/* In/out : */
+/* Return : See enum AVCDec_Status for return values. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecodeSlice(AVCHandle *avcHandle, uint8 *buffer,
+ int buf_size)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+ AVCDec_Status status;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ return AVCDEC_PICTURE_OUTPUT_READY; // to flushout frame buffers
+ }
+
+ if (video->newSlice)
+ {
+ /* 2. Check NAL type */
+ if (buffer == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->prev_nal_unit_type = video->nal_unit_type;
+ video->forbidden_bit = buffer[0] >> 7;
+ video->nal_ref_idc = (buffer[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(buffer[0] & 0x1F);
+
+
+ if (video->nal_unit_type == AVC_NALTYPE_AUD)
+ {
+ return AVCDEC_SUCCESS;
+ }
+
+ if (video->nal_unit_type != AVC_NALTYPE_SLICE &&
+ video->nal_unit_type != AVC_NALTYPE_IDR)
+ {
+ return AVCDEC_FAIL; /* not supported */
+ }
+
+
+
+ if (video->nal_unit_type >= 2 && video->nal_unit_type <= 4)
+ {
+ return AVCDEC_FAIL; /* not supported */
+ }
+ else
+ {
+ video->slice_data_partitioning = FALSE;
+ }
+
+ video->newSlice = FALSE;
+ /* Initialize bitstream structure*/
+ BitstreamInit(bitstream, buffer + 1, buf_size - 1);
+
+
+ /* 2.1 Decode Slice Header (separate function)*/
+ status = DecodeSliceHeader(decvid, video, bitstream);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->newSlice = TRUE;
+ return status;
+ }
+
+ if (video->sliceHdr->frame_num != video->prevFrameNum || (video->sliceHdr->first_mb_in_slice < (uint)video->mbNum && video->currSeqParams->constrained_set1_flag == 1))
+ {
+ video->newPic = TRUE;
+ if (video->numMBs > 0)
+ {
+ // Conceal missing MBs of previously decoded frame
+ ConcealSlice(decvid, video->PicSizeInMbs - video->numMBs, video->PicSizeInMbs); // Conceal
+ video->numMBs = 0;
+
+ // DeblockPicture(video); // No need to deblock
+
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ AVCNalUnitType temp = video->nal_unit_type;
+ video->nal_unit_type = video->prev_nal_unit_type;
+ StorePictureInDPB(avcHandle, video);
+ video->nal_unit_type = temp;
+ video->mbNum = 0; // MC_Conceal
+ return AVCDEC_PICTURE_OUTPUT_READY;
+ }
+ }
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevFrameNum = 0;
+ video->PrevRefFrameNum = 0;
+ }
+
+ if (!video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
+ { /* no gaps allowed, frame_num has to increase by one only */
+ /* if(sliceHdr->frame_num != (video->PrevRefFrameNum + 1)%video->MaxFrameNum) */
+ if (video->sliceHdr->frame_num != video->PrevRefFrameNum && video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
+ {
+ // Conceal missing MBs of previously decoded frame
+ video->numMBs = 0;
+ video->newPic = TRUE;
+ video->prevFrameNum++; // FIX
+ video->PrevRefFrameNum++;
+ AVCNalUnitType temp = video->nal_unit_type;
+ video->nal_unit_type = AVC_NALTYPE_SLICE; //video->prev_nal_unit_type;
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ video->currFS->IsOutputted = 0x01;
+ video->currFS->IsReference = 3;
+ video->currFS->IsLongTerm = 0;
+
+ DecodePOC(video);
+ /* find an empty memory from DPB and assigned to currPic */
+ DPBInitPic(video, video->PrevRefFrameNum % video->MaxFrameNum);
+ RefListInit(video);
+ ConcealSlice(decvid, 0, video->PicSizeInMbs); // Conceal
+ video->currFS->IsOutputted |= 0x02;
+ //conceal frame
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ video->mbNum = 0; // Conceal
+ StorePictureInDPB(avcHandle, video);
+ video->nal_unit_type = temp;
+
+ return AVCDEC_PICTURE_OUTPUT_READY;
+ }
+ }
+ }
+
+ if (video->newPic == TRUE)
+ {
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ video->newSlice = TRUE;
+
+ /* function pointer setting at slice-level */
+ // OPTIMIZE
+ decvid->residual_block = &residual_block_cavlc;
+
+ /* derive picture order count */
+ if (video->newPic == TRUE)
+ {
+ video->numMBs = video->PicSizeInMbs;
+
+ if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
+ {
+ if (video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
+ {
+ status = fill_frame_num_gap(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->numMBs = 0;
+ return status;
+ }
+
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->numMBs = 0;
+ return status;
+ }
+
+
+ }
+ }
+ /* if there's gap in the frame_num, we have to fill in the gap with
+ imaginary frames that won't get used for short-term ref. */
+ /* see fill_frame_num_gap() in JM */
+
+
+ DecodePOC(video);
+ /* find an empty memory from DPB and assigned to currPic */
+ DPBInitPic(video, video->CurrPicNum);
+
+ video->currPic->isReference = TRUE; // FIX
+
+ if (video->nal_ref_idc == 0)
+ {
+ video->currPic->isReference = FALSE;
+ video->currFS->IsOutputted |= 0x02; /* The MASK 0x02 means not needed for reference, or returned */
+ /* node need to check for freeing of this buffer */
+ }
+
+ FMOInit(video);
+
+ if (video->currPic->isReference)
+ {
+ video->PrevRefFrameNum = video->sliceHdr->frame_num;
+ }
+
+
+ video->prevFrameNum = video->sliceHdr->frame_num;
+ }
+
+ video->newPic = FALSE;
+
+
+ /* Initialize refListIdx for this picture */
+ RefListInit(video);
+
+ /* Re-order the reference list according to the ref_pic_list_reordering() */
+ status = (AVCDec_Status)ReOrderList(video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* 2.2 Decode Slice. */
+ status = (AVCDec_Status)DecodeSlice(decvid);
+
+ video->slice_id++; // slice
+
+ if (status == AVCDEC_PICTURE_READY)
+ {
+ /* 3. Check complete picture */
+#ifndef MB_BASED_DEBLOCK
+ /* 3.1 Deblock */
+ DeblockPicture(video);
+#endif
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ status = (AVCDec_Status)StorePictureInDPB(avcHandle, video); // CHECK check the retunr status
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ video->PrevRefFrameNum = 0;
+ video->prevFrameNum = 0;
+ video->prevPicOrderCntMsb = 0;
+ video->prevPicOrderCntLsb = video->TopFieldOrderCnt;
+ video->prevFrameNumOffset = 0;
+ }
+ else
+ {
+ video->prevPicOrderCntMsb = video->PicOrderCntMsb;
+ video->prevPicOrderCntLsb = video->sliceHdr->pic_order_cnt_lsb;
+ video->prevFrameNumOffset = video->FrameNumOffset;
+ }
+
+ return AVCDEC_PICTURE_READY;
+ }
+ else if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecGetOutput() */
+/* Date : 11/3/2003 */
+/* Purpose : Get the next picture according to PicOrderCnt. */
+/* In/out : */
+/* Return : AVCFrameIO structure */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetOutput(AVCHandle *avcHandle, int *indx, int *release, AVCFrameIO *output)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecPicBuffer *dpb;
+ AVCFrameStore *oldestFrame = NULL;
+ int i, first = 1;
+ int count_frame = 0;
+ int index = 0;
+ int min_poc = 0;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ dpb = video->decPicBuf;
+
+ if (dpb->num_fs == 0)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* search for the oldest frame_num in dpb */
+ /* extension to field decoding, we have to search for every top_field/bottom_field within
+ each frame in the dpb. This code only works for frame based.*/
+
+ if (video->mem_mgr_ctrl_eq_5 == FALSE)
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsOutputted & 0x01) == 0)
+ {
+ count_frame++;
+ if (first)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ first = 0;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ if (dpb->fs[i]->PicOrderCnt < min_poc)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsOutputted & 0x01) == 0 && dpb->fs[i] != video->currFS)
+ {
+ count_frame++;
+ if (first)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ first = 0;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ if (dpb->fs[i]->PicOrderCnt < min_poc)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ }
+ }
+
+ if (count_frame < 2 && video->nal_unit_type != AVC_NALTYPE_IDR)
+ {
+ video->mem_mgr_ctrl_eq_5 = FALSE; // FIX
+ }
+ else if (count_frame < 1 && video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i] == video->currFS && (dpb->fs[i]->IsOutputted & 0x01) == 0)
+ {
+ oldestFrame = dpb->fs[i];
+ index = i;
+ break;
+ }
+ }
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ }
+ }
+
+ if (oldestFrame == NULL)
+ {
+
+ /* Check for Mem_mgmt_operation_5 based forced output */
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ /* looking for the one not used or not reference and has been outputted */
+ if (dpb->fs[i]->IsReference == 0 && dpb->fs[i]->IsOutputted == 3)
+ {
+ break;
+ }
+ }
+ if (i < dpb->num_fs)
+ {
+ /* there are frames available for decoding */
+ return AVCDEC_FAIL; /* no frame to be outputted */
+ }
+
+
+ /* no free frame available, we have to release one to continue decoding */
+ int MinIdx = 0;
+ int32 MinFrameNumWrap = 0x7FFFFFFF;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i]->IsReference && !dpb->fs[i]->IsLongTerm)
+ {
+ if (dpb->fs[i]->FrameNumWrap < MinFrameNumWrap)
+ {
+ MinFrameNumWrap = dpb->fs[i]->FrameNumWrap;
+ MinIdx = i;
+ }
+ }
+ }
+ /* mark the frame with smallest PicOrderCnt to be unused for reference */
+ dpb->fs[MinIdx]->IsReference = 0;
+ dpb->fs[MinIdx]->IsLongTerm = 0;
+ dpb->fs[MinIdx]->frame.isReference = FALSE;
+ dpb->fs[MinIdx]->frame.isLongTerm = FALSE;
+ dpb->fs[MinIdx]->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (dpb->fs[MinIdx]->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, MinIdx);
+ }
+#endif
+ return AVCDEC_FAIL;
+ }
+ /* MASK 0x01 means the frame is outputted (for display). A frame gets freed when it is
+ outputted (0x01) and not needed for reference (0x02) */
+ oldestFrame->IsOutputted |= 0x01;
+
+ if (oldestFrame->IsOutputted == 3)
+ {
+ *release = 1; /* flag to release the buffer */
+ }
+ else
+ {
+ *release = 0;
+ }
+ /* do not release buffer here, release it after it is sent to the sink node */
+
+ output->YCbCr[0] = oldestFrame->frame.Sl;
+ output->YCbCr[1] = oldestFrame->frame.Scb;
+ output->YCbCr[2] = oldestFrame->frame.Scr;
+ output->height = oldestFrame->frame.height;
+ output->pitch = oldestFrame->frame.width;
+ output->disp_order = oldestFrame->PicOrderCnt;
+ output->coding_order = oldestFrame->FrameNum;
+ output->id = (uint32) oldestFrame->base_dpb; /* use the pointer as the id */
+ *indx = index;
+
+
+
+ return AVCDEC_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCDecReset() */
+/* Date : 03/04/2004 */
+/* Purpose : Reset decoder, prepare it for a new IDR frame. */
+/* In/out : */
+/* Return : void */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF void PVAVCDecReset(AVCHandle *avcHandle)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecPicBuffer *dpb;
+ int i;
+
+ if (decvid == NULL)
+ {
+ return;
+ }
+
+ video = decvid->common;
+ dpb = video->decPicBuf;
+
+ /* reset the DPB */
+
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ dpb->fs[i]->IsLongTerm = 0;
+ dpb->fs[i]->IsReference = 0;
+ dpb->fs[i]->IsOutputted = 3;
+ dpb->fs[i]->frame.isReference = 0;
+ dpb->fs[i]->frame.isLongTerm = 0;
+ }
+
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ video->newPic = TRUE;
+ video->newSlice = TRUE;
+ video->currPic = NULL;
+ video->currFS = NULL;
+ video->prevRefPic = NULL;
+ video->prevFrameNum = 0;
+ video->PrevRefFrameNum = 0;
+ video->prevFrameNumOffset = 0;
+ video->FrameNumOffset = 0;
+ video->mbNum = 0;
+ video->numMBs = 0;
+
+ return ;
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCCleanUpDecoder() */
+/* Date : 11/4/2003 */
+/* Purpose : Clean up the decoder, free all memories allocated. */
+/* In/out : */
+/* Return : void */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF void PVAVCCleanUpDecoder(AVCHandle *avcHandle)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ void *userData = avcHandle->userData;
+ int i;
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCCleanUpDecoder", -1, -1);
+
+ if (decvid != NULL)
+ {
+ video = decvid->common;
+ if (video != NULL)
+ {
+ if (video->MbToSliceGroupMap != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->MbToSliceGroupMap);
+ }
+
+#ifdef MB_BASED_DEBLOCK
+ if (video->intra_pred_top != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top);
+ }
+ if (video->intra_pred_top_cb != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cb);
+ }
+ if (video->intra_pred_top_cr != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cr);
+ }
+#endif
+ if (video->mblock != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->mblock);
+ }
+
+ if (video->decPicBuf != NULL)
+ {
+ CleanUpDPB(avcHandle, video);
+ avcHandle->CBAVC_Free(userData, (int)video->decPicBuf);
+ }
+
+ if (video->sliceHdr != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->sliceHdr);
+ }
+
+ avcHandle->CBAVC_Free(userData, (int)video); /* last thing to do */
+
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ if (decvid->picParams[i] != NULL)
+ {
+ if (decvid->picParams[i]->slice_group_id != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]->slice_group_id);
+ }
+ avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]);
+ }
+ }
+ for (i = 0; i < 32; i++)
+ {
+ if (decvid->seqParams[i] != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->seqParams[i]);
+ }
+ }
+ if (decvid->bitstream != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->bitstream);
+ }
+
+
+ avcHandle->CBAVC_Free(userData, (int)decvid);
+ }
+
+
+ return ;
+}
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h b/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h
new file mode 100644
index 0000000..bd1bc59
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains bitstream related functions.
+@publishedAll
+*/
+
+#ifndef _AVCDEC_BITSTREAM_H_
+#define _AVCDEC_BITSTREAM_H_
+
+#include "avcdec_lib.h"
+
+#define WORD_SIZE 32 /* this can vary, default to 32 bit for now */
+
+#ifndef __cplusplus
+
+#define AVC_GETDATA(x,y) userData->AVC_GetData(x,y)
+
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define BitstreamFlushBits(A,B) {(A)->bitcnt += (B); (A)->incnt -= (B); (A)->curr_word <<= (B);}
+
+ AVCDec_Status AVC_BitstreamFillCache(AVCDecBitstream *stream);
+ /**
+ This function populates bitstream structure.
+ \param "stream" "Pointer to bitstream structure."
+ \param "buffer" "Pointer to the bitstream buffer."
+ \param "size" "Size of the buffer."
+ \param "nal_size" "Size of the NAL unit."
+ \param "resetall" "Flag for reset everything."
+ \return "AVCDEC_SUCCESS for success and AVCDEC_FAIL for fail."
+ */
+ AVCDec_Status BitstreamInit(AVCDecBitstream *stream, uint8 *buffer, int size);
+
+ /**
+ This function reads next aligned word and remove the emulation prevention code
+ if necessary.
+ \param "stream" "Pointer to bitstream structure."
+ \return "Next word."
+ */
+ uint BitstreamNextWord(AVCDecBitstream *stream);
+
+ /**
+ This function reads nBits bits from the current position and advance the pointer.
+ \param "stream" "Pointer to bitstream structure."
+ \param "nBits" "Number of bits to be read."
+ \param "code" "Point to the read value."
+ \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
+ is greater than the word-size, AVCDEC_PACKET_LOSS or
+ AVCDEC_NO_DATA if callback to get data fails."
+ */
+ AVCDec_Status BitstreamReadBits(AVCDecBitstream *stream, int nBits, uint *code);
+
+ /**
+ This function shows nBits bits from the current position without advancing the pointer.
+ \param "stream" "Pointer to bitstream structure."
+ \param "nBits" "Number of bits to be read."
+ \param "code" "Point to the read value."
+ \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
+ is greater than the word-size, AVCDEC_NO_DATA if it needs
+ to callback to get data."
+ */
+ AVCDec_Status BitstreamShowBits(AVCDecBitstream *stream, int nBits, uint *code);
+
+
+ /**
+ This function flushes nBits bits from the current position.
+ \param "stream" "Pointer to bitstream structure."
+ \param "nBits" "Number of bits to be read."
+ \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
+ is greater than the word-size It will not call back to get
+ more data. Users should call BitstreamShowBits to determine
+ how much they want to flush."
+ */
+
+ /**
+ This function read 1 bit from the current position and advance the pointer.
+ \param "stream" "Pointer to bitstream structure."
+ \param "nBits" "Number of bits to be read."
+ \param "code" "Point to the read value."
+ \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
+ is greater than the word-size, AVCDEC_PACKET_LOSS or
+ AVCDEC_NO_DATA if callback to get data fails."
+ */
+ AVCDec_Status BitstreamRead1Bit(AVCDecBitstream *stream, uint *code);
+
+ /**
+ This function checks whether the current bit position is byte-aligned or not.
+ \param "stream" "Pointer to the bitstream structure."
+ \return "TRUE if byte-aligned, FALSE otherwise."
+ */
+ bool byte_aligned(AVCDecBitstream *stream);
+ AVCDec_Status BitstreamByteAlign(AVCDecBitstream *stream);
+ /**
+ This function checks whether there are more RBSP data before the trailing bits.
+ \param "stream" "Pointer to the bitstream structure."
+ \return "TRUE if yes, FALSE otherwise."
+ */
+ bool more_rbsp_data(AVCDecBitstream *stream);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _AVCDEC_BITSTREAM_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_int.h b/media/libstagefright/codecs/avc/dec/src/avcdec_int.h
new file mode 100644
index 0000000..878f9b3
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avcdec_int.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC decoder library
+and necessary type defitionitions and enumerations.
+Naming convention for variables:
+lower_case_with_under_line is syntax element in subclause 7.2 and 7.3
+noUnderLine or NoUnderLine is derived variables defined somewhere else in the draft
+ or introduced by this decoder library.
+@publishedAll
+*/
+
+#ifndef _AVCDEC_INT_H_
+#define _AVCDEC_INT_H_
+
+#include "avcint_common.h"
+#include "avcdec_api.h"
+
+
+/**
+Bitstream structure contains bitstream related parameters such as the pointer
+to the buffer, the current byte position and bit position.
+@publishedAll
+*/
+typedef struct tagDecBitstream
+{
+ uint8 *bitstreamBuffer; /* pointer to buffer memory */
+ int nal_size; /* size of the current NAL unit */
+ int data_end_pos; /* bitstreamBuffer size in bytes */
+ int read_pos; /* next position to read from bitstreamBuffer */
+ uint curr_word; /* byte-swapped (MSB left) current word read from buffer */
+ int bit_left; /* number of bit left in current_word */
+ uint next_word; /* in case for old data in previous buffer hasn't been flushed. */
+ int incnt; /* bit left in the prev_word */
+ int incnt_next;
+ int bitcnt;
+ void *userData;
+} AVCDecBitstream;
+
+/**
+This structure is the main object for AVC decoder library providing access to all
+global variables. It is allocated at PVAVCInitDecoder and freed at PVAVCCleanUpDecoder.
+@publishedAll
+*/
+typedef struct tagDecObject
+{
+
+ AVCCommonObj *common;
+
+ AVCDecBitstream *bitstream; /* for current NAL */
+
+ /* sequence parameter set */
+ AVCSeqParamSet *seqParams[32]; /* Array of pointers, get allocated at arrival of new seq_id */
+
+ /* picture parameter set */
+ AVCPicParamSet *picParams[256]; /* Array of pointers to picture param set structures */
+
+ /* For internal operation, scratch memory for MV, prediction, transform, etc.*/
+ uint ref_idx_l0[4]; /* [mbPartIdx], te(v) */
+ uint ref_idx_l1[4];
+
+ /* function pointers */
+ AVCDec_Status(*residual_block)(struct tagDecObject*, int, int,
+ int *, int *, int *);
+ /* Application control data */
+ AVCHandle *avcHandle;
+ void (*AVC_DebugLog)(AVCLogType type, char *string1, char *string2);
+ /*bool*/
+ uint debugEnable;
+
+} AVCDecObject;
+
+#endif /* _AVCDEC_INT_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h b/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h
new file mode 100644
index 0000000..fdead05
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h
@@ -0,0 +1,555 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains declarations of internal functions for AVC decoder library.
+@publishedAll
+*/
+#ifndef _AVCDEC_LIB_H_
+#define _AVCDEC_LIB_H_
+
+#include "avclib_common.h"
+#include "avcdec_int.h"
+
+/*----------- avcdec_api.c -------------*/
+/**
+This function takes out the emulation prevention bytes from the input to creat RBSP.
+The result is written over the input bitstream.
+\param "nal_unit" "(I/O) Pointer to the input buffer."
+\param "size" "(I/O) Pointer to the size of the input/output buffer."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status EBSPtoRBSP(uint8 *nal_unit, int *size);
+
+/*------------- pred_intra.c ---------------*/
+/**
+This function is the main entry point to intra prediction operation on a
+macroblock.
+\param "video" "Pointer to AVCCommonObj."
+*/
+AVCStatus IntraMBPrediction(AVCCommonObj *video);
+
+void SaveNeighborForIntraPred(AVCCommonObj *video, int offset);
+
+AVCStatus Intra_4x4(AVCCommonObj *video, int component, int SubBlock_indx, uint8 *comp);
+void Intra_4x4_Vertical(AVCCommonObj *video, int block_offset);
+void Intra_4x4_Horizontal(AVCCommonObj *video, int pitch, int block_offset);
+void Intra_4x4_DC(AVCCommonObj *video, int pitch, int block_offset, AVCNeighborAvailability *availability);
+void Intra_4x4_Down_Left(AVCCommonObj *video, int block_offset, AVCNeighborAvailability *availability);
+void Intra_4x4_Diagonal_Down_Right(AVCCommonObj *video, int pitch, int block_offset);
+void Intra_4x4_Diagonal_Vertical_Right(AVCCommonObj *video, int pitch, int block_offset);
+void Intra_4x4_Diagonal_Horizontal_Down(AVCCommonObj *video, int pitch, int block_offset);
+void Intra_4x4_Vertical_Left(AVCCommonObj *video, int block_offset, AVCNeighborAvailability *availability);
+void Intra_4x4_Horizontal_Up(AVCCommonObj *video, int pitch, int block_offset);
+void Intra_16x16_Vertical(AVCCommonObj *video);
+void Intra_16x16_Horizontal(AVCCommonObj *video, int pitch);
+void Intra_16x16_DC(AVCCommonObj *video, int pitch);
+void Intra_16x16_Plane(AVCCommonObj *video, int pitch);
+void Intra_Chroma_DC(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
+void Intra_Chroma_Horizontal(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
+void Intra_Chroma_Vertical(AVCCommonObj *video, uint8 *predCb, uint8 *predCr);
+void Intra_Chroma_Plane(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
+
+/*------------ pred_inter.c ---------------*/
+/**
+This function is the main entrance to inter prediction operation for
+a macroblock. For decoding, this function also calls inverse transform and
+compensation.
+\param "video" "Pointer to AVCCommonObj."
+\return "void"
+*/
+void InterMBPrediction(AVCCommonObj *video);
+
+/**
+This function is called for luma motion compensation.
+\param "ref" "Pointer to the origin of a reference luma."
+\param "picwidth" "Width of the picture."
+\param "picheight" "Height of the picture."
+\param "x_pos" "X-coordinate of the predicted block in quarter pel resolution."
+\param "y_pos" "Y-coordinate of the predicted block in quarter pel resolution."
+\param "pred" "Pointer to the output predicted block."
+\param "pred_pitch" "Width of pred."
+\param "blkwidth" "Width of the current partition."
+\param "blkheight" "Height of the current partition."
+\return "void"
+*/
+void LumaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight);
+
+/**
+Functions below are special cases for luma motion compensation.
+LumaFullPelMC is for full pixel motion compensation.
+LumaBorderMC is for interpolation in only one dimension.
+LumaCrossMC is for interpolation in one dimension and half point in the other dimension.
+LumaDiagonalMC is for interpolation in diagonal direction.
+
+\param "ref" "Pointer to the origin of a reference luma."
+\param "picwidth" "Width of the picture."
+\param "picheight" "Height of the picture."
+\param "x_pos" "X-coordinate of the predicted block in full pel resolution."
+\param "y_pos" "Y-coordinate of the predicted block in full pel resolution."
+\param "dx" "Fraction of x_pos in quarter pel."
+\param "dy" "Fraction of y_pos in quarter pel."
+\param "curr" "Pointer to the current partition in the current picture."
+\param "residue" "Pointer to the current partition for the residue block."
+\param "blkwidth" "Width of the current partition."
+\param "blkheight" "Height of the current partition."
+\return "void"
+*/
+void CreatePad(uint8 *ref, int picwidth, int picheight, int x_pos, int y_pos,
+ uint8 *out, int blkwidth, int blkheight);
+
+void FullPelMC(uint8 *in, int inwidth, uint8 *out, int outpitch,
+ int blkwidth, int blkheight);
+
+void HorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx);
+
+void HorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx);
+
+void HorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight);
+
+void VertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy);
+
+void VertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight);
+
+void VertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy);
+
+void DiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+ uint8 *out, int outpitch,
+ int blkwidth, int blkheight);
+
+
+void ChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos, uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight);
+
+void ChromaFullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight) ;
+void ChromaBorderMC(uint8 *ref, int picwidth, int dx, int dy,
+ uint8 *pred, int pred_pitch, int blkwidth, int blkheight);
+void ChromaDiagonalMC(uint8 *ref, int picwidth, int dx, int dy,
+ uint8 *pred, int pred_pitch, int blkwidth, int blkheight);
+
+void ChromaFullPelMCOutside(uint8 *ref, uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight, int x_inc,
+ int y_inc0, int y_inc1, int x_mid, int y_mid);
+void ChromaBorderMCOutside(uint8 *ref, int picwidth, int dx, int dy,
+ uint8 *pred, int pred_pitch, int blkwidth, int blkheight,
+ int x_inc, int z_inc, int y_inc0, int y_inc1, int x_mid, int y_mid);
+void ChromaDiagonalMCOutside(uint8 *ref, int picwidth,
+ int dx, int dy, uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight, int x_inc, int z_inc,
+ int y_inc0, int y_inc1, int x_mid, int y_mid);
+
+void ChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+void ChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+
+/*----------- slice.c ---------------*/
+/**
+This function performs the main decoding loop for slice data including
+INTRA/INTER prediction, transform and quantization and compensation.
+See decode_frame_slice() in JM.
+\param "video" "Pointer to AVCDecObject."
+\return "AVCDEC_SUCCESS for success, AVCDEC_PICTURE_READY for end-of-picture and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status DecodeSlice(AVCDecObject *video);
+AVCDec_Status ConcealSlice(AVCDecObject *decvid, int mbnum_start, int mbnum_end);
+/**
+This function performs the decoding of one macroblock.
+\param "video" "Pointer to AVCDecObject."
+\param "prevMbSkipped" "A value derived in 7.3.4."
+\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status DecodeMB(AVCDecObject *video);
+
+/**
+This function performs macroblock prediction type decoding as in subclause 7.3.5.1.
+\param "video" "Pointer to AVCCommonObj."
+\param "currMB" "Pointer to the current macroblock."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
+
+/**
+This function performs sub-macroblock prediction type decoding as in subclause 7.3.5.2.
+\param "video" "Pointer to AVCCommonObj."
+\param "currMB" "Pointer to the current macroblock."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
+
+/**
+This function interprets the mb_type and sets necessary information
+when the slice type is AVC_I_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretMBModeI(AVCMacroblock *mblock, uint mb_type);
+
+/**
+This function interprets the mb_type and sets necessary information
+when the slice type is AVC_P_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretMBModeP(AVCMacroblock *mblock, uint mb_type);
+
+/**
+This function interprets the mb_type and sets necessary information
+when the slice type is AVC_B_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretMBModeB(AVCMacroblock *mblock, uint mb_type);
+
+/**
+This function interprets the mb_type and sets necessary information
+when the slice type is AVC_SI_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretMBModeSI(AVCMacroblock *mblock, uint mb_type);
+
+/**
+This function interprets the sub_mb_type and sets necessary information
+when the slice type is AVC_P_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "sub_mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretSubMBModeP(AVCMacroblock *mblock, uint *sub_mb_type);
+
+/**
+This function interprets the sub_mb_type and sets necessary information
+when the slice type is AVC_B_SLICE.
+in the macroblock structure.
+\param "mblock" "Pointer to current AVCMacroblock."
+\param "sub_mb_type" "From the syntax bitstream."
+\return "void"
+*/
+void InterpretSubMBModeB(AVCMacroblock *mblock, uint *sub_mb_type);
+
+/**
+This function decodes the Intra4x4 prediction mode from neighboring information
+and from the decoded syntax.
+\param "video" "Pointer to AVCCommonObj."
+\param "currMB" "Pointer to current macroblock."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status DecodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
+
+/*----------- vlc.c -------------------*/
+/**
+This function reads and decodes Exp-Golomb codes.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "codeNum" "Pointer to the value of the codeNum."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status ue_v(AVCDecBitstream *bitstream, uint *codeNum);
+
+/**
+This function reads and decodes signed Exp-Golomb codes.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "value" "Pointer to syntax element value."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status se_v(AVCDecBitstream *bitstream, int *value);
+
+/**
+This function reads and decodes signed Exp-Golomb codes for
+32 bit codeword.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "value" "Pointer to syntax element value."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status se_v32bit(AVCDecBitstream *bitstream, int32 *value);
+
+/**
+This function reads and decodes truncated Exp-Golomb codes.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "value" "Pointer to syntax element value."
+\param "range" "Range of the value as input to determine the algorithm."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status te_v(AVCDecBitstream *bitstream, uint *value, uint range);
+
+/**
+This function parse Exp-Golomb code from the bitstream.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "leadingZeros" "Pointer to the number of leading zeros."
+\param "infobits" "Pointer to the value after leading zeros and the first one.
+ The total number of bits read is 2*leadingZeros + 1."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status GetEGBitstring(AVCDecBitstream *bitstream, int *leadingZeros, int *infobits);
+
+/**
+This function parse Exp-Golomb code from the bitstream for 32 bit codewords.
+\param "bitstream" "Pointer to AVCDecBitstream."
+\param "leadingZeros" "Pointer to the number of leading zeros."
+\param "infobits" "Pointer to the value after leading zeros and the first one.
+ The total number of bits read is 2*leadingZeros + 1."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status GetEGBitstring32bit(AVCDecBitstream *bitstream, int *leadingZeros, uint32 *infobits);
+
+/**
+This function performs CAVLC decoding of the CBP (coded block pattern) of a macroblock
+by calling ue_v() and then mapping the codeNum to the corresponding CBP value.
+\param "currMB" "Pointer to the current AVCMacroblock structure."
+\param "stream" "Pointer to the AVCDecBitstream."
+\return "void"
+*/
+AVCDec_Status DecodeCBP(AVCMacroblock *currMB, AVCDecBitstream *stream);
+
+/**
+This function decodes the syntax for trailing ones and total coefficient.
+Subject to optimization.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "TrailingOnes" "Pointer to the trailing one variable output."
+\param "TotalCoeff" "Pointer to the total coefficient variable output."
+\param "nC" "Context for number of nonzero coefficient (prediction context)."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_TotalCoeffTrailingOnes(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff, int nC);
+
+/**
+This function decodes the syntax for trailing ones and total coefficient for
+chroma DC block. Subject to optimization.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "TrailingOnes" "Pointer to the trailing one variable output."
+\param "TotalCoeff" "Pointer to the total coefficient variable output."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_TotalCoeffTrailingOnesChromaDC(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff);
+
+/**
+This function decode a VLC table with 2 output.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "lentab" "Table for code length."
+\param "codtab" "Table for code value."
+\param "tabwidth" "Width of the table or alphabet size of the first output."
+\param "tabheight" "Height of the table or alphabet size of the second output."
+\param "code1" "Pointer to the first output."
+\param "code2" "Pointer to the second output."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status code_from_bitstream_2d(AVCDecBitstream *stream, int *lentab, int *codtab, int tabwidth,
+ int tabheight, int *code1, int *code2);
+
+/**
+This function decodes the level_prefix VLC value as in Table 9-6.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "code" "Pointer to the output."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_LevelPrefix(AVCDecBitstream *stream, uint *code);
+
+/**
+This function decodes total_zeros VLC syntax as in Table 9-7 and 9-8.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "code" "Pointer to the output."
+\param "TotalCoeff" "Context parameter."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_TotalZeros(AVCDecBitstream *stream, int *code, int TotalCoeff);
+
+/**
+This function decodes total_zeros VLC syntax for chroma DC as in Table 9-9.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "code" "Pointer to the output."
+\param "TotalCoeff" "Context parameter."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_TotalZerosChromaDC(AVCDecBitstream *stream, int *code, int TotalCoeff);
+
+/**
+This function decodes run_before VLC syntax as in Table 9-10.
+\param "stream" "Pointer to the AVCDecBitstream."
+\param "code" "Pointer to the output."
+\param "zeroLeft" "Context parameter."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status ce_RunBefore(AVCDecBitstream *stream, int *code, int zeroLeft);
+
+/*----------- header.c -------------------*/
+/**
+This function parses vui_parameters.
+\param "decvid" "Pointer to AVCDecObject."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status vui_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCSeqParamSet *currSPS);
+AVCDec_Status sei_payload(AVCDecObject *decvid, AVCDecBitstream *stream, uint payloadType, uint payloadSize);
+
+AVCDec_Status buffering_period(AVCDecObject *decvid, AVCDecBitstream *stream);
+AVCDec_Status pic_timing(AVCDecObject *decvid, AVCDecBitstream *stream);
+AVCDec_Status recovery_point(AVCDecObject *decvid, AVCDecBitstream *stream);
+AVCDec_Status dec_ref_pic_marking_repetition(AVCDecObject *decvid, AVCDecBitstream *stream);
+AVCDec_Status motion_constrained_slice_group_set(AVCDecObject *decvid, AVCDecBitstream *stream);
+
+
+/**
+This function parses hrd_parameters.
+\param "decvid" "Pointer to AVCDecObject."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status hrd_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCHRDParams *HRDParam);
+
+/**
+This function decodes the syntax in sequence parameter set slice and fill up the AVCSeqParamSet
+structure.
+\param "decvid" "Pointer to AVCDecObject."
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status DecodeSPS(AVCDecObject *decvid, AVCDecBitstream *stream);
+
+/**
+This function decodes the syntax in picture parameter set and fill up the AVCPicParamSet
+structure.
+\param "decvid" "Pointer to AVCDecObject."
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
+*/
+AVCDec_Status DecodePPS(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream);
+AVCDec_Status DecodeSEI(AVCDecObject *decvid, AVCDecBitstream *stream);
+
+/**
+This function decodes slice header, calls related functions such as
+reference picture list reordering, prediction weight table, decode ref marking.
+See FirstPartOfSliceHeader() and RestOfSliceHeader() in JM.
+\param "decvid" "Pointer to AVCDecObject."
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status DecodeSliceHeader(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream);
+
+/**
+This function performes necessary operations to create dummy frames when
+there is a gap in frame_num.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status fill_frame_num_gap(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function decodes ref_pic_list_reordering related syntax and fill up the AVCSliceHeader
+structure.
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+\param "sliceHdr" "Pointer to AVCSliceHdr."
+\param "slice_type" "Value of slice_type - 5 if greater than 5."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status ref_pic_list_reordering(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type);
+
+/**
+This function decodes dec_ref_pic_marking related syntax and fill up the AVCSliceHeader
+structure.
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+\param "sliceHdr" "Pointer to AVCSliceHdr."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+*/
+AVCDec_Status dec_ref_pic_marking(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr);
+
+/**
+This function performs POC related operation prior to decoding a picture
+\param "video" "Pointer to AVCCommonObj."
+\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
+See also PostPOC() for initialization of some variables.
+*/
+AVCDec_Status DecodePOC(AVCCommonObj *video);
+
+
+
+/*------------ residual.c ------------------*/
+/**
+This function decodes the intra pcm data and fill it in the corresponding location
+on the current picture.
+\param "video" "Pointer to AVCCommonObj."
+\param "stream" "Pointer to AVCDecBitstream."
+*/
+AVCDec_Status DecodeIntraPCM(AVCCommonObj *video, AVCDecBitstream *stream);
+
+/**
+This function performs residual syntax decoding as well as quantization and transformation of
+the decoded coefficients. See subclause 7.3.5.3.
+\param "video" "Pointer to AVCDecObject."
+\param "currMB" "Pointer to current macroblock."
+*/
+AVCDec_Status residual(AVCDecObject *video, AVCMacroblock *currMB);
+
+/**
+This function performs CAVLC syntax decoding to get the run and level information of the coefficients.
+\param "video" "Pointer to AVCDecObject."
+\param "type" "One of AVCResidualType for a particular 4x4 block."
+\param "bx" "Horizontal block index."
+\param "by" "Vertical block index."
+\param "level" "Pointer to array of level for output."
+\param "run" "Pointer to array of run for output."
+\param "numcoeff" "Pointer to the total number of nonzero coefficients."
+\return "AVCDEC_SUCCESS for success."
+*/
+AVCDec_Status residual_block_cavlc(AVCDecObject *video, int nC, int maxNumCoeff,
+ int *level, int *run, int *numcoeff);
+
+#endif /* _AVCDEC_LIB_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/header.cpp b/media/libstagefright/codecs/avc/dec/src/header.cpp
new file mode 100644
index 0000000..8681e2b
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/header.cpp
@@ -0,0 +1,1391 @@
+/* ------------------------------------------------------------------
+ * 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 "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+#include "avcdec_api.h"
+
+/** see subclause 7.4.2.1 */
+AVCDec_Status DecodeSPS(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ AVCDec_Status status = AVCDEC_SUCCESS;
+ AVCSeqParamSet *seqParam;
+ uint temp;
+ int i;
+ uint profile_idc, constrained_set0_flag, constrained_set1_flag, constrained_set2_flag;
+ uint level_idc, seq_parameter_set_id;
+ void *userData = decvid->avcHandle->userData;
+ AVCHandle *avcHandle = decvid->avcHandle;
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "DecodeSPS", -1, -1);
+
+ BitstreamReadBits(stream, 8, &profile_idc);
+ BitstreamRead1Bit(stream, &constrained_set0_flag);
+// if (profile_idc != 66 && constrained_set0_flag != 1)
+// {
+// return AVCDEC_FAIL;
+// }
+ BitstreamRead1Bit(stream, &constrained_set1_flag);
+ BitstreamRead1Bit(stream, &constrained_set2_flag);
+ BitstreamReadBits(stream, 5, &temp);
+ BitstreamReadBits(stream, 8, &level_idc);
+ if (level_idc > 51)
+ {
+ return AVCDEC_FAIL;
+ }
+ if (mapLev2Idx[level_idc] == 255)
+ {
+ return AVCDEC_FAIL;
+ }
+ ue_v(stream, &seq_parameter_set_id);
+
+ if (seq_parameter_set_id > 31)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* Allocate sequence param set for seqParams[seq_parameter_set_id]. */
+ if (decvid->seqParams[seq_parameter_set_id] == NULL) /* allocate seqParams[id] */
+ {
+ decvid->seqParams[seq_parameter_set_id] =
+ (AVCSeqParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSeqParamSet), DEFAULT_ATTR);
+
+ if (decvid->seqParams[seq_parameter_set_id] == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+ }
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "done alloc seqParams", -1, -1);
+
+ seqParam = decvid->seqParams[seq_parameter_set_id];
+
+ seqParam->profile_idc = profile_idc;
+ seqParam->constrained_set0_flag = constrained_set0_flag;
+ seqParam->constrained_set1_flag = constrained_set1_flag;
+ seqParam->constrained_set2_flag = constrained_set2_flag;
+ seqParam->level_idc = level_idc;
+ seqParam->seq_parameter_set_id = seq_parameter_set_id;
+
+ /* continue decoding SPS */
+ ue_v(stream, &(seqParam->log2_max_frame_num_minus4));
+
+ if (seqParam->log2_max_frame_num_minus4 > 12)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ ue_v(stream, &(seqParam->pic_order_cnt_type));
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 1", seqParam->log2_max_frame_num_minus4, seqParam->pic_order_cnt_type);
+
+ if (seqParam->pic_order_cnt_type == 0)
+ {
+ ue_v(stream, &(seqParam->log2_max_pic_order_cnt_lsb_minus4));
+ }
+ else if (seqParam->pic_order_cnt_type == 1)
+ { // MC_CHECK
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->delta_pic_order_always_zero_flag));
+ se_v32bit(stream, &(seqParam->offset_for_non_ref_pic));
+ se_v32bit(stream, &(seqParam->offset_for_top_to_bottom_field));
+ ue_v(stream, &(seqParam->num_ref_frames_in_pic_order_cnt_cycle));
+
+ for (i = 0; i < (int)(seqParam->num_ref_frames_in_pic_order_cnt_cycle); i++)
+ {
+ se_v32bit(stream, &(seqParam->offset_for_ref_frame[i]));
+ }
+ }
+
+ ue_v(stream, &(seqParam->num_ref_frames));
+
+ if (seqParam->num_ref_frames > 16)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 2", seqParam->num_ref_frames, -1);
+
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->gaps_in_frame_num_value_allowed_flag));
+ ue_v(stream, &(seqParam->pic_width_in_mbs_minus1));
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "picwidth", seqParam->pic_width_in_mbs_minus1, -1);
+
+ ue_v(stream, &(seqParam->pic_height_in_map_units_minus1));
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "picwidth", seqParam->pic_height_in_map_units_minus1, -1);
+
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->frame_mbs_only_flag));
+
+ seqParam->mb_adaptive_frame_field_flag = 0; /* default value */
+ if (!seqParam->frame_mbs_only_flag)
+ {
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->mb_adaptive_frame_field_flag));
+ }
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 3", seqParam->frame_mbs_only_flag, -1);
+
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->direct_8x8_inference_flag));
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 4", seqParam->direct_8x8_inference_flag, -1);
+
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->frame_cropping_flag));
+ seqParam->frame_crop_left_offset = 0; /* default value */
+ seqParam->frame_crop_right_offset = 0;/* default value */
+ seqParam->frame_crop_top_offset = 0;/* default value */
+ seqParam->frame_crop_bottom_offset = 0;/* default value */
+ if (seqParam->frame_cropping_flag)
+ {
+ ue_v(stream, &(seqParam->frame_crop_left_offset));
+ ue_v(stream, &(seqParam->frame_crop_right_offset));
+ ue_v(stream, &(seqParam->frame_crop_top_offset));
+ ue_v(stream, &(seqParam->frame_crop_bottom_offset));
+ }
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 5", seqParam->frame_cropping_flag, -1);
+
+ BitstreamRead1Bit(stream, (uint*)&(seqParam->vui_parameters_present_flag));
+ if (seqParam->vui_parameters_present_flag)
+ {
+ status = vui_parameters(decvid, stream, seqParam);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+ }
+
+ return status;
+}
+
+
+AVCDec_Status vui_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCSeqParamSet *currSPS)
+{
+ uint temp;
+ uint temp32;
+ uint aspect_ratio_idc, overscan_appopriate_flag, video_format, video_full_range_flag;
+ /* aspect_ratio_info_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ BitstreamReadBits(stream, 8, &aspect_ratio_idc);
+ if (aspect_ratio_idc == 255)
+ {
+ /* sar_width */
+ BitstreamReadBits(stream, 16, &temp);
+ /* sar_height */
+ BitstreamReadBits(stream, 16, &temp);
+ }
+ }
+ /* overscan_info_present */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ BitstreamRead1Bit(stream, &overscan_appopriate_flag);
+ }
+ /* video_signal_type_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ BitstreamReadBits(stream, 3, &video_format);
+ BitstreamRead1Bit(stream, &video_full_range_flag);
+ /* colour_description_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* colour_primaries */
+ BitstreamReadBits(stream, 8, &temp);
+ /* transfer_characteristics */
+ BitstreamReadBits(stream, 8, &temp);
+ /* matrix coefficients */
+ BitstreamReadBits(stream, 8, &temp);
+ }
+ }
+ /* chroma_loc_info_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* chroma_sample_loc_type_top_field */
+ ue_v(stream, &temp);
+ /* chroma_sample_loc_type_bottom_field */
+ ue_v(stream, &temp);
+ }
+
+ /* timing_info_present_flag*/
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* num_unit_in_tick*/
+ BitstreamReadBits(stream, 32, &temp32);
+ /* time_scale */
+ BitstreamReadBits(stream, 32, &temp32);
+ /* fixed_frame_rate_flag */
+ BitstreamRead1Bit(stream, &temp);
+ }
+
+ /* nal_hrd_parameters_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ currSPS->vui_parameters.nal_hrd_parameters_present_flag = temp;
+ if (temp)
+ {
+ hrd_parameters(decvid, stream, &(currSPS->vui_parameters.nal_hrd_parameters));
+ }
+ /* vcl_hrd_parameters_present_flag*/
+ BitstreamRead1Bit(stream, &temp);
+ currSPS->vui_parameters.vcl_hrd_parameters_present_flag = temp;
+ if (temp)
+ {
+ hrd_parameters(decvid, stream, &(currSPS->vui_parameters.vcl_hrd_parameters));
+ }
+ if (currSPS->vui_parameters.nal_hrd_parameters_present_flag || currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
+ {
+ /* low_delay_hrd_flag */
+ BitstreamRead1Bit(stream, &temp);
+ }
+ /* pic_struct_present_flag */
+ BitstreamRead1Bit(stream, &temp);
+ currSPS->vui_parameters.pic_struct_present_flag = temp;
+ /* bitstream_restriction_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* motion_vectors_over_pic_boundaries_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* max_bytes_per_pic_denom */
+ ue_v(stream, &temp);
+ /* max_bits_per_mb_denom */
+ ue_v(stream, &temp);
+ /* log2_max_mv_length_horizontal */
+ ue_v(stream, &temp);
+ /* log2_max_mv_length_vertical */
+ ue_v(stream, &temp);
+ /* num_reorder_frames */
+ ue_v(stream, &temp);
+ /* max_dec_frame_buffering */
+ ue_v(stream, &temp);
+ }
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status hrd_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCHRDParams *HRDParam)
+{
+ OSCL_UNUSED_ARG(decvid);
+ uint temp;
+ uint cpb_cnt_minus1;
+ uint i;
+ ue_v(stream, &cpb_cnt_minus1);
+ HRDParam->cpb_cnt_minus1 = cpb_cnt_minus1;
+ /* bit_rate_scale */
+ BitstreamReadBits(stream, 4, &temp);
+ /* cpb_size_scale */
+ BitstreamReadBits(stream, 4, &temp);
+ for (i = 0; i <= cpb_cnt_minus1; i++)
+ {
+ /* bit_rate_value_minus1[i] */
+ ue_v(stream, &temp);
+ /* cpb_size_value_minus1[i] */
+ ue_v(stream, &temp);
+ /* cbr_flag[i] */
+ ue_v(stream, &temp);
+ }
+ /* initial_cpb_removal_delay_length_minus1 */
+ BitstreamReadBits(stream, 5, &temp);
+ /* cpb_removal_delay_length_minus1 */
+ BitstreamReadBits(stream, 5, &temp);
+ HRDParam->cpb_removal_delay_length_minus1 = temp;
+ /* dpb_output_delay_length_minus1 */
+ BitstreamReadBits(stream, 5, &temp);
+ HRDParam->dpb_output_delay_length_minus1 = temp;
+ /* time_offset_length */
+ BitstreamReadBits(stream, 5, &temp);
+ HRDParam->time_offset_length = temp;
+ return AVCDEC_SUCCESS;
+}
+
+
+/** see subclause 7.4.2.2 */
+AVCDec_Status DecodePPS(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream)
+{
+ AVCPicParamSet *picParam;
+ AVCDec_Status status;
+ int i, iGroup, numBits;
+ int PicWidthInMbs, PicHeightInMapUnits, PicSizeInMapUnits;
+ uint pic_parameter_set_id, seq_parameter_set_id;
+ void *userData = decvid->avcHandle->userData;
+ AVCHandle *avcHandle = decvid->avcHandle;
+
+ ue_v(stream, &pic_parameter_set_id);
+ if (pic_parameter_set_id > 255)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ ue_v(stream, &seq_parameter_set_id);
+
+ if (seq_parameter_set_id > 31)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* 2.1 if picParams[pic_param_set_id] is NULL, allocate it. */
+ if (decvid->picParams[pic_parameter_set_id] == NULL)
+ {
+ decvid->picParams[pic_parameter_set_id] =
+ (AVCPicParamSet*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCPicParamSet), DEFAULT_ATTR);
+ if (decvid->picParams[pic_parameter_set_id] == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ decvid->picParams[pic_parameter_set_id]->slice_group_id = NULL;
+ }
+
+ video->currPicParams = picParam = decvid->picParams[pic_parameter_set_id];
+ picParam->seq_parameter_set_id = seq_parameter_set_id;
+ picParam->pic_parameter_set_id = pic_parameter_set_id;
+
+ BitstreamRead1Bit(stream, (uint*)&(picParam->entropy_coding_mode_flag));
+ if (picParam->entropy_coding_mode_flag)
+ {
+ status = AVCDEC_FAIL;
+ goto clean_up;
+ }
+ BitstreamRead1Bit(stream, (uint*)&(picParam->pic_order_present_flag));
+ ue_v(stream, &(picParam->num_slice_groups_minus1));
+
+ if (picParam->num_slice_groups_minus1 > MAX_NUM_SLICE_GROUP - 1)
+ {
+ status = AVCDEC_FAIL;
+ goto clean_up;
+ }
+
+ picParam->slice_group_change_rate_minus1 = 0; /* default value */
+ if (picParam->num_slice_groups_minus1 > 0)
+ {
+ ue_v(stream, &(picParam->slice_group_map_type));
+ if (picParam->slice_group_map_type == 0)
+ {
+ for (iGroup = 0; iGroup <= (int)picParam->num_slice_groups_minus1; iGroup++)
+ {
+ ue_v(stream, &(picParam->run_length_minus1[iGroup]));
+ }
+ }
+ else if (picParam->slice_group_map_type == 2)
+ { // MC_CHECK <= or <
+ for (iGroup = 0; iGroup < (int)picParam->num_slice_groups_minus1; iGroup++)
+ {
+ ue_v(stream, &(picParam->top_left[iGroup]));
+ ue_v(stream, &(picParam->bottom_right[iGroup]));
+ }
+ }
+ else if (picParam->slice_group_map_type == 3 ||
+ picParam->slice_group_map_type == 4 ||
+ picParam->slice_group_map_type == 5)
+ {
+ BitstreamRead1Bit(stream, (uint*)&(picParam->slice_group_change_direction_flag));
+ ue_v(stream, &(picParam->slice_group_change_rate_minus1));
+ }
+ else if (picParam->slice_group_map_type == 6)
+ {
+ ue_v(stream, &(picParam->pic_size_in_map_units_minus1));
+
+ numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
+ i = picParam->num_slice_groups_minus1;
+ while (i > 0)
+ {
+ numBits++;
+ i >>= 1;
+ }
+
+ i = picParam->seq_parameter_set_id;
+ if (decvid->seqParams[i] == NULL)
+ {
+ status = AVCDEC_FAIL;
+ goto clean_up;
+ }
+
+
+ PicWidthInMbs = decvid->seqParams[i]->pic_width_in_mbs_minus1 + 1;
+ PicHeightInMapUnits = decvid->seqParams[i]->pic_height_in_map_units_minus1 + 1 ;
+ PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits ;
+
+ /* information has to be consistent with the seq_param */
+ if ((int)picParam->pic_size_in_map_units_minus1 != PicSizeInMapUnits - 1)
+ {
+ status = AVCDEC_FAIL;
+ goto clean_up;
+ }
+
+ if (picParam->slice_group_id)
+ {
+ avcHandle->CBAVC_Free(userData, (int)picParam->slice_group_id);
+ }
+ picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * PicSizeInMapUnits, DEFAULT_ATTR);
+ if (picParam->slice_group_id == NULL)
+ {
+ status = AVCDEC_MEMORY_FAIL;
+ goto clean_up;
+ }
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ BitstreamReadBits(stream, numBits, &(picParam->slice_group_id[i]));
+ }
+ }
+
+ }
+
+ ue_v(stream, &(picParam->num_ref_idx_l0_active_minus1));
+ if (picParam->num_ref_idx_l0_active_minus1 > 31)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ ue_v(stream, &(picParam->num_ref_idx_l1_active_minus1));
+ if (picParam->num_ref_idx_l1_active_minus1 > 31)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ BitstreamRead1Bit(stream, (uint*)&(picParam->weighted_pred_flag));
+ BitstreamReadBits(stream, 2, &(picParam->weighted_bipred_idc));
+ if (picParam->weighted_bipred_idc > 2)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ se_v(stream, &(picParam->pic_init_qp_minus26));
+ if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ se_v(stream, &(picParam->pic_init_qs_minus26));
+ if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ se_v(stream, &(picParam->chroma_qp_index_offset));
+ if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
+ {
+ status = AVCDEC_FAIL; /* out of range */
+ status = AVCDEC_FAIL; /* out of range */
+ goto clean_up;
+ }
+
+ BitstreamReadBits(stream, 3, &pic_parameter_set_id);
+ picParam->deblocking_filter_control_present_flag = pic_parameter_set_id >> 2;
+ picParam->constrained_intra_pred_flag = (pic_parameter_set_id >> 1) & 1;
+ picParam->redundant_pic_cnt_present_flag = pic_parameter_set_id & 1;
+
+ return AVCDEC_SUCCESS;
+clean_up:
+ if (decvid->picParams[pic_parameter_set_id])
+ {
+ if (picParam->slice_group_id)
+ {
+ avcHandle->CBAVC_Free(userData, (int)picParam->slice_group_id);
+ }
+ decvid->picParams[pic_parameter_set_id]->slice_group_id = NULL;
+ avcHandle->CBAVC_Free(userData, (int)decvid->picParams[pic_parameter_set_id]);
+ decvid->picParams[pic_parameter_set_id] = NULL;
+ return status;
+ }
+ return AVCDEC_SUCCESS;
+}
+
+
+/* FirstPartOfSliceHeader();
+ RestOfSliceHeader() */
+/** see subclause 7.4.3 */
+AVCDec_Status DecodeSliceHeader(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCPicParamSet *currPPS;
+ AVCSeqParamSet *currSPS;
+ AVCDec_Status status;
+ uint idr_pic_id;
+ int slice_type, temp, i;
+
+ ue_v(stream, &(sliceHdr->first_mb_in_slice));
+ ue_v(stream, (uint*)&slice_type);
+
+ if (sliceHdr->first_mb_in_slice != 0)
+ {
+ if ((int)sliceHdr->slice_type >= 5 && slice_type != (int)sliceHdr->slice_type - 5)
+ {
+ return AVCDEC_FAIL; /* slice type doesn't follow the first slice in the picture */
+ }
+ }
+ sliceHdr->slice_type = (AVCSliceType) slice_type;
+ if (slice_type > 4)
+ {
+ slice_type -= 5;
+ }
+
+ if (slice_type == 1 || slice_type > 2)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video->slice_type = (AVCSliceType) slice_type;
+
+ ue_v(stream, &(sliceHdr->pic_parameter_set_id));
+ /* end FirstPartSliceHeader() */
+ /* begin RestOfSliceHeader() */
+ /* after getting pic_parameter_set_id, we have to load corresponding SPS and PPS */
+ if (sliceHdr->pic_parameter_set_id > 255)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ if (decvid->picParams[sliceHdr->pic_parameter_set_id] == NULL)
+ return AVCDEC_FAIL; /* PPS doesn't exist */
+
+ currPPS = video->currPicParams = decvid->picParams[sliceHdr->pic_parameter_set_id];
+
+ if (decvid->seqParams[currPPS->seq_parameter_set_id] == NULL)
+ return AVCDEC_FAIL; /* SPS doesn't exist */
+
+ currSPS = video->currSeqParams = decvid->seqParams[currPPS->seq_parameter_set_id];
+
+ if (currPPS->seq_parameter_set_id != video->seq_parameter_set_id)
+ {
+ video->seq_parameter_set_id = currPPS->seq_parameter_set_id;
+ status = (AVCDec_Status)AVCConfigureSequence(decvid->avcHandle, video, false);
+ if (status != AVCDEC_SUCCESS)
+ return status;
+ video->level_idc = currSPS->level_idc;
+ }
+
+ /* derived variables from SPS */
+ video->MaxFrameNum = 1 << (currSPS->log2_max_frame_num_minus4 + 4);
+ // MC_OPTIMIZE
+ video->PicWidthInMbs = currSPS->pic_width_in_mbs_minus1 + 1;
+ video->PicWidthInSamplesL = video->PicWidthInMbs * 16 ;
+ video->PicWidthInSamplesC = video->PicWidthInMbs * 8 ;
+ video->PicHeightInMapUnits = currSPS->pic_height_in_map_units_minus1 + 1 ;
+ video->PicSizeInMapUnits = video->PicWidthInMbs * video->PicHeightInMapUnits ;
+ video->FrameHeightInMbs = (2 - currSPS->frame_mbs_only_flag) * video->PicHeightInMapUnits ;
+
+ /* derived from PPS */
+ video->SliceGroupChangeRate = currPPS->slice_group_change_rate_minus1 + 1;
+
+ /* then we can continue decoding slice header */
+
+ BitstreamReadBits(stream, currSPS->log2_max_frame_num_minus4 + 4, &(sliceHdr->frame_num));
+
+ if (video->currFS == NULL && sliceHdr->frame_num != 0)
+ {
+ video->prevFrameNum = video->PrevRefFrameNum = sliceHdr->frame_num - 1;
+ }
+
+ if (!currSPS->frame_mbs_only_flag)
+ {
+ BitstreamRead1Bit(stream, &(sliceHdr->field_pic_flag));
+ if (sliceHdr->field_pic_flag)
+ {
+ return AVCDEC_FAIL;
+ }
+ }
+
+ /* derived variables from slice header*/
+ video->PicHeightInMbs = video->FrameHeightInMbs;
+ video->PicHeightInSamplesL = video->PicHeightInMbs * 16;
+ video->PicHeightInSamplesC = video->PicHeightInMbs * 8;
+ video->PicSizeInMbs = video->PicWidthInMbs * video->PicHeightInMbs;
+
+ if (sliceHdr->first_mb_in_slice >= video->PicSizeInMbs)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->MaxPicNum = video->MaxFrameNum;
+ video->CurrPicNum = sliceHdr->frame_num;
+
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ if (sliceHdr->frame_num != 0)
+ {
+ return AVCDEC_FAIL;
+ }
+ ue_v(stream, &idr_pic_id);
+ }
+
+ sliceHdr->delta_pic_order_cnt_bottom = 0; /* default value */
+ sliceHdr->delta_pic_order_cnt[0] = 0; /* default value */
+ sliceHdr->delta_pic_order_cnt[1] = 0; /* default value */
+ if (currSPS->pic_order_cnt_type == 0)
+ {
+ BitstreamReadBits(stream, currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4,
+ &(sliceHdr->pic_order_cnt_lsb));
+ video->MaxPicOrderCntLsb = 1 << (currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4);
+ if (sliceHdr->pic_order_cnt_lsb > video->MaxPicOrderCntLsb - 1)
+ return AVCDEC_FAIL; /* out of range */
+
+ if (currPPS->pic_order_present_flag)
+ {
+ se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt_bottom));
+ }
+ }
+ if (currSPS->pic_order_cnt_type == 1 && !currSPS->delta_pic_order_always_zero_flag)
+ {
+ se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt[0]));
+ if (currPPS->pic_order_present_flag)
+ {
+ se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt[1]));
+ }
+ }
+
+ sliceHdr->redundant_pic_cnt = 0; /* default value */
+ if (currPPS->redundant_pic_cnt_present_flag)
+ {
+ // MC_CHECK
+ ue_v(stream, &(sliceHdr->redundant_pic_cnt));
+ if (sliceHdr->redundant_pic_cnt > 127) /* out of range */
+ return AVCDEC_FAIL;
+
+ if (sliceHdr->redundant_pic_cnt > 0) /* redundant picture */
+ return AVCDEC_FAIL; /* not supported */
+ }
+ sliceHdr->num_ref_idx_l0_active_minus1 = currPPS->num_ref_idx_l0_active_minus1;
+ sliceHdr->num_ref_idx_l1_active_minus1 = currPPS->num_ref_idx_l1_active_minus1;
+
+ if (slice_type == AVC_P_SLICE)
+ {
+ BitstreamRead1Bit(stream, &(sliceHdr->num_ref_idx_active_override_flag));
+ if (sliceHdr->num_ref_idx_active_override_flag)
+ {
+ ue_v(stream, &(sliceHdr->num_ref_idx_l0_active_minus1));
+ }
+ else /* the following condition is not allowed if the flag is zero */
+ {
+ if ((slice_type == AVC_P_SLICE) && currPPS->num_ref_idx_l0_active_minus1 > 15)
+ {
+ return AVCDEC_FAIL; /* not allowed */
+ }
+ }
+ }
+
+
+ if (sliceHdr->num_ref_idx_l0_active_minus1 > 15 ||
+ sliceHdr->num_ref_idx_l1_active_minus1 > 15)
+ {
+ return AVCDEC_FAIL; /* not allowed */
+ }
+ /* if MbaffFrameFlag =1,
+ max value of index is num_ref_idx_l0_active_minus1 for frame MBs and
+ 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1 for field MBs */
+
+ /* ref_pic_list_reordering() */
+ status = ref_pic_list_reordering(video, stream, sliceHdr, slice_type);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+
+
+ if (video->nal_ref_idc != 0)
+ {
+ dec_ref_pic_marking(video, stream, sliceHdr);
+ }
+ se_v(stream, &(sliceHdr->slice_qp_delta));
+
+ video->QPy = 26 + currPPS->pic_init_qp_minus26 + sliceHdr->slice_qp_delta;
+ if (video->QPy > 51 || video->QPy < 0)
+ {
+ video->QPy = AVC_CLIP3(0, 51, video->QPy);
+// return AVCDEC_FAIL;
+ }
+ video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->QPy + video->currPicParams->chroma_qp_index_offset)];
+
+ video->QPy_div_6 = (video->QPy * 43) >> 8;
+ video->QPy_mod_6 = video->QPy - 6 * video->QPy_div_6;
+
+ video->QPc_div_6 = (video->QPc * 43) >> 8;
+ video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
+
+ sliceHdr->slice_alpha_c0_offset_div2 = 0;
+ sliceHdr->slice_beta_offset_div_2 = 0;
+ sliceHdr->disable_deblocking_filter_idc = 0;
+ video->FilterOffsetA = video->FilterOffsetB = 0;
+
+ if (currPPS->deblocking_filter_control_present_flag)
+ {
+ ue_v(stream, &(sliceHdr->disable_deblocking_filter_idc));
+ if (sliceHdr->disable_deblocking_filter_idc > 2)
+ {
+ return AVCDEC_FAIL; /* out of range */
+ }
+ if (sliceHdr->disable_deblocking_filter_idc != 1)
+ {
+ se_v(stream, &(sliceHdr->slice_alpha_c0_offset_div2));
+ if (sliceHdr->slice_alpha_c0_offset_div2 < -6 ||
+ sliceHdr->slice_alpha_c0_offset_div2 > 6)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->FilterOffsetA = sliceHdr->slice_alpha_c0_offset_div2 << 1;
+
+ se_v(stream, &(sliceHdr->slice_beta_offset_div_2));
+ if (sliceHdr->slice_beta_offset_div_2 < -6 ||
+ sliceHdr->slice_beta_offset_div_2 > 6)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->FilterOffsetB = sliceHdr->slice_beta_offset_div_2 << 1;
+ }
+ }
+
+ if (currPPS->num_slice_groups_minus1 > 0 && currPPS->slice_group_map_type >= 3
+ && currPPS->slice_group_map_type <= 5)
+ {
+ /* Ceil(Log2(PicSizeInMapUnits/(float)SliceGroupChangeRate + 1)) */
+ temp = video->PicSizeInMapUnits / video->SliceGroupChangeRate;
+ if (video->PicSizeInMapUnits % video->SliceGroupChangeRate)
+ {
+ temp++;
+ }
+ i = 0;
+ temp++;
+ while (temp)
+ {
+ temp >>= 1;
+ i++;
+ }
+
+ BitstreamReadBits(stream, i, &(sliceHdr->slice_group_change_cycle));
+ video->MapUnitsInSliceGroup0 =
+ AVC_MIN(sliceHdr->slice_group_change_cycle * video->SliceGroupChangeRate, video->PicSizeInMapUnits);
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+
+AVCDec_Status fill_frame_num_gap(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDec_Status status;
+ int CurrFrameNum;
+ int UnusedShortTermFrameNum;
+ int tmp1 = video->sliceHdr->delta_pic_order_cnt[0];
+ int tmp2 = video->sliceHdr->delta_pic_order_cnt[1];
+ int tmp3 = video->CurrPicNum;
+ int tmp4 = video->sliceHdr->adaptive_ref_pic_marking_mode_flag;
+ UnusedShortTermFrameNum = (video->prevFrameNum + 1) % video->MaxFrameNum;
+ CurrFrameNum = video->sliceHdr->frame_num;
+
+ video->sliceHdr->delta_pic_order_cnt[0] = 0;
+ video->sliceHdr->delta_pic_order_cnt[1] = 0;
+ while (CurrFrameNum != UnusedShortTermFrameNum)
+ {
+ video->CurrPicNum = UnusedShortTermFrameNum;
+ video->sliceHdr->frame_num = UnusedShortTermFrameNum;
+
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS) /* no buffer available */
+ {
+ return status;
+ }
+ DecodePOC(video);
+ DPBInitPic(video, UnusedShortTermFrameNum);
+
+
+ video->currFS->PicOrderCnt = video->PicOrderCnt;
+ video->currFS->FrameNum = video->sliceHdr->frame_num;
+
+ /* initialize everything to zero */
+ video->currFS->IsOutputted = 0x01;
+ video->currFS->IsReference = 3;
+ video->currFS->IsLongTerm = 0;
+ video->currFS->frame.isReference = TRUE;
+ video->currFS->frame.isLongTerm = FALSE;
+
+ video->sliceHdr->adaptive_ref_pic_marking_mode_flag = 0;
+
+ status = (AVCDec_Status)StorePictureInDPB(avcHandle, video); // MC_CHECK check the return status
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->prevFrameNum = UnusedShortTermFrameNum;
+ UnusedShortTermFrameNum = (UnusedShortTermFrameNum + 1) % video->MaxFrameNum;
+ }
+ video->sliceHdr->frame_num = CurrFrameNum;
+ video->CurrPicNum = tmp3;
+ video->sliceHdr->delta_pic_order_cnt[0] = tmp1;
+ video->sliceHdr->delta_pic_order_cnt[1] = tmp2;
+ video->sliceHdr->adaptive_ref_pic_marking_mode_flag = tmp4;
+ return AVCDEC_SUCCESS;
+}
+
+/** see subclause 7.4.3.1 */
+AVCDec_Status ref_pic_list_reordering(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type)
+{
+ int i;
+
+ if (slice_type != AVC_I_SLICE)
+ {
+ BitstreamRead1Bit(stream, &(sliceHdr->ref_pic_list_reordering_flag_l0));
+ if (sliceHdr->ref_pic_list_reordering_flag_l0)
+ {
+ i = 0;
+ do
+ {
+ ue_v(stream, &(sliceHdr->reordering_of_pic_nums_idc_l0[i]));
+ if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 ||
+ sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1)
+ {
+ ue_v(stream, &(sliceHdr->abs_diff_pic_num_minus1_l0[i]));
+ if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 &&
+ sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum / 2 - 1)
+ {
+ return AVCDEC_FAIL; /* out of range */
+ }
+ if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1 &&
+ sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum / 2 - 2)
+ {
+ return AVCDEC_FAIL; /* out of range */
+ }
+ }
+ else if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 2)
+ {
+ ue_v(stream, &(sliceHdr->long_term_pic_num_l0[i]));
+ }
+ i++;
+ }
+ while (sliceHdr->reordering_of_pic_nums_idc_l0[i-1] != 3
+ && i <= (int)sliceHdr->num_ref_idx_l0_active_minus1 + 1) ;
+ }
+ }
+ return AVCDEC_SUCCESS;
+}
+
+/** see subclause 7.4.3.3 */
+AVCDec_Status dec_ref_pic_marking(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr)
+{
+ int i;
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ BitstreamRead1Bit(stream, &(sliceHdr->no_output_of_prior_pics_flag));
+ BitstreamRead1Bit(stream, &(sliceHdr->long_term_reference_flag));
+ if (sliceHdr->long_term_reference_flag == 0) /* used for short-term */
+ {
+ video->MaxLongTermFrameIdx = -1; /* no long-term frame indx */
+ }
+ else /* used for long-term */
+ {
+ video->MaxLongTermFrameIdx = 0;
+ video->LongTermFrameIdx = 0;
+ }
+ }
+ else
+ {
+ BitstreamRead1Bit(stream, &(sliceHdr->adaptive_ref_pic_marking_mode_flag));
+ if (sliceHdr->adaptive_ref_pic_marking_mode_flag)
+ {
+ i = 0;
+ do
+ {
+ ue_v(stream, &(sliceHdr->memory_management_control_operation[i]));
+ if (sliceHdr->memory_management_control_operation[i] == 1 ||
+ sliceHdr->memory_management_control_operation[i] == 3)
+ {
+ ue_v(stream, &(sliceHdr->difference_of_pic_nums_minus1[i]));
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 2)
+ {
+ ue_v(stream, &(sliceHdr->long_term_pic_num[i]));
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 3 ||
+ sliceHdr->memory_management_control_operation[i] == 6)
+ {
+ ue_v(stream, &(sliceHdr->long_term_frame_idx[i]));
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 4)
+ {
+ ue_v(stream, &(sliceHdr->max_long_term_frame_idx_plus1[i]));
+ }
+ i++;
+ }
+ while (sliceHdr->memory_management_control_operation[i-1] != 0 && i < MAX_DEC_REF_PIC_MARKING);
+ if (i >= MAX_DEC_REF_PIC_MARKING)
+ {
+ return AVCDEC_FAIL; /* we're screwed!!, not enough memory */
+ }
+ }
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see subclause 8.2.1 Decoding process for picture order count. */
+AVCDec_Status DecodePOC(AVCCommonObj *video)
+{
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ int i;
+
+ switch (currSPS->pic_order_cnt_type)
+ {
+ case 0: /* POC MODE 0 , subclause 8.2.1.1 */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevPicOrderCntMsb = 0;
+ video->prevPicOrderCntLsb = 0;
+ }
+
+ /* Calculate the MSBs of current picture */
+ if (sliceHdr->pic_order_cnt_lsb < video->prevPicOrderCntLsb &&
+ (video->prevPicOrderCntLsb - sliceHdr->pic_order_cnt_lsb) >= (video->MaxPicOrderCntLsb / 2))
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb + video->MaxPicOrderCntLsb;
+ else if (sliceHdr->pic_order_cnt_lsb > video->prevPicOrderCntLsb &&
+ (sliceHdr->pic_order_cnt_lsb - video->prevPicOrderCntLsb) > (video->MaxPicOrderCntLsb / 2))
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb - video->MaxPicOrderCntLsb;
+ else
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb;
+
+ /* JVT-I010 page 81 is different from JM7.3 */
+
+
+ video->PicOrderCnt = video->TopFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
+ video->BottomFieldOrderCnt = video->TopFieldOrderCnt + sliceHdr->delta_pic_order_cnt_bottom;
+
+ break;
+
+
+ case 1: /* POC MODE 1, subclause 8.2.1.2 */
+ /* calculate FrameNumOffset */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevFrameNumOffset = 0;
+ video->FrameNumOffset = 0;
+ }
+ else if (video->prevFrameNum > sliceHdr->frame_num)
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+ }
+ else
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset;
+ }
+ /* calculate absFrameNum */
+ if (currSPS->num_ref_frames_in_pic_order_cnt_cycle)
+ {
+ video->absFrameNum = video->FrameNumOffset + sliceHdr->frame_num;
+ }
+ else
+ {
+ video->absFrameNum = 0;
+ }
+
+ if (video->absFrameNum > 0 && video->nal_ref_idc == 0)
+ {
+ video->absFrameNum--;
+ }
+
+ /* derive picOrderCntCycleCnt and frameNumInPicOrderCntCycle */
+ if (video->absFrameNum > 0)
+ {
+ video->picOrderCntCycleCnt = (video->absFrameNum - 1) / currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+ video->frameNumInPicOrderCntCycle = (video->absFrameNum - 1) % currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+ }
+ /* derive expectedDeltaPerPicOrderCntCycle */
+ video->expectedDeltaPerPicOrderCntCycle = 0;
+ for (i = 0; i < (int)currSPS->num_ref_frames_in_pic_order_cnt_cycle; i++)
+ {
+ video->expectedDeltaPerPicOrderCntCycle += currSPS->offset_for_ref_frame[i];
+ }
+ /* derive expectedPicOrderCnt */
+ if (video->absFrameNum)
+ {
+ video->expectedPicOrderCnt = video->picOrderCntCycleCnt * video->expectedDeltaPerPicOrderCntCycle;
+ for (i = 0; i <= video->frameNumInPicOrderCntCycle; i++)
+ {
+ video->expectedPicOrderCnt += currSPS->offset_for_ref_frame[i];
+ }
+ }
+ else
+ {
+ video->expectedPicOrderCnt = 0;
+ }
+
+ if (video->nal_ref_idc == 0)
+ {
+ video->expectedPicOrderCnt += currSPS->offset_for_non_ref_pic;
+ }
+ /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
+
+ video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
+ video->BottomFieldOrderCnt = video->TopFieldOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[1];
+
+ video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
+
+
+ break;
+
+
+ case 2: /* POC MODE 2, subclause 8.2.1.3 */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->FrameNumOffset = 0;
+ }
+ else if (video->prevFrameNum > sliceHdr->frame_num)
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+ }
+ else
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset;
+ }
+ /* derive tempPicOrderCnt, we just use PicOrderCnt */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->PicOrderCnt = 0;
+ }
+ else if (video->nal_ref_idc == 0)
+ {
+ video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num) - 1;
+ }
+ else
+ {
+ video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num);
+ }
+ video->TopFieldOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCnt;
+ break;
+ default:
+ return AVCDEC_FAIL;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+
+AVCDec_Status DecodeSEI(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ OSCL_UNUSED_ARG(decvid);
+ OSCL_UNUSED_ARG(stream);
+ return AVCDEC_SUCCESS;
+}
+
+AVCDec_Status sei_payload(AVCDecObject *decvid, AVCDecBitstream *stream, uint payloadType, uint payloadSize)
+{
+ AVCDec_Status status = AVCDEC_SUCCESS;
+ uint i;
+ switch (payloadType)
+ {
+ case 0:
+ /* buffering period SEI */
+ status = buffering_period(decvid, stream);
+ break;
+ case 1:
+ /* picture timing SEI */
+ status = pic_timing(decvid, stream);
+ break;
+ case 2:
+
+ case 3:
+
+ case 4:
+
+ case 5:
+
+ case 8:
+
+ case 9:
+
+ case 10:
+
+ case 11:
+
+ case 12:
+
+ case 13:
+
+ case 14:
+
+ case 15:
+
+ case 16:
+
+ case 17:
+ for (i = 0; i < payloadSize; i++)
+ {
+ BitstreamFlushBits(stream, 8);
+ }
+ break;
+ case 6:
+ /* recovery point SEI */
+ status = recovery_point(decvid, stream);
+ break;
+ case 7:
+ /* decoded reference picture marking repetition SEI */
+ status = dec_ref_pic_marking_repetition(decvid, stream);
+ break;
+
+ case 18:
+ /* motion-constrained slice group set SEI */
+ status = motion_constrained_slice_group_set(decvid, stream);
+ break;
+ default:
+ /* reserved_sei_message */
+ for (i = 0; i < payloadSize; i++)
+ {
+ BitstreamFlushBits(stream, 8);
+ }
+ break;
+ }
+ BitstreamByteAlign(stream);
+ return status;
+}
+
+AVCDec_Status buffering_period(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ AVCSeqParamSet *currSPS;
+ uint seq_parameter_set_id;
+ uint temp;
+ uint i;
+ ue_v(stream, &seq_parameter_set_id);
+ if (seq_parameter_set_id > 31)
+ {
+ return AVCDEC_FAIL;
+ }
+
+// decvid->common->seq_parameter_set_id = seq_parameter_set_id;
+
+ currSPS = decvid->seqParams[seq_parameter_set_id];
+ if (currSPS->vui_parameters.nal_hrd_parameters_present_flag)
+ {
+ for (i = 0; i <= currSPS->vui_parameters.nal_hrd_parameters.cpb_cnt_minus1; i++)
+ {
+ /* initial_cpb_removal_delay[i] */
+ BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ /*initial _cpb_removal_delay_offset[i] */
+ BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ }
+ }
+
+ if (currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
+ {
+ for (i = 0; i <= currSPS->vui_parameters.vcl_hrd_parameters.cpb_cnt_minus1; i++)
+ {
+ /* initial_cpb_removal_delay[i] */
+ BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ /*initial _cpb_removal_delay_offset[i] */
+ BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ }
+ }
+
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status pic_timing(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ AVCSeqParamSet *currSPS;
+ uint temp, NumClockTs = 0, time_offset_length = 24, full_timestamp_flag;
+ uint i;
+
+ currSPS = decvid->seqParams[decvid->common->seq_parameter_set_id];
+
+ if (currSPS->vui_parameters.nal_hrd_parameters_present_flag)
+ {
+ BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.dpb_output_delay_length_minus1 + 1, &temp);
+ time_offset_length = currSPS->vui_parameters.nal_hrd_parameters.time_offset_length;
+ }
+ else if (currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
+ {
+ BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
+ BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1, &temp);
+ time_offset_length = currSPS->vui_parameters.vcl_hrd_parameters.time_offset_length;
+ }
+
+ if (currSPS->vui_parameters.pic_struct_present_flag)
+ {
+ /* pic_struct */
+ BitstreamReadBits(stream, 4, &temp);
+
+ switch (temp)
+ {
+ case 0:
+ case 1:
+ case 2:
+ NumClockTs = 1;
+ break;
+ case 3:
+ case 4:
+ case 7:
+ NumClockTs = 2;
+ break;
+ case 5:
+ case 6:
+ case 8:
+ NumClockTs = 3;
+ break;
+ default:
+ NumClockTs = 0;
+ break;
+ }
+
+ for (i = 0; i < NumClockTs; i++)
+ {
+ /* clock_timestamp_flag[i] */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* ct_type */
+ BitstreamReadBits(stream, 2, &temp);
+ /* nuit_field_based_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* counting_type */
+ BitstreamReadBits(stream, 5, &temp);
+ /* full_timestamp_flag */
+ BitstreamRead1Bit(stream, &temp);
+ full_timestamp_flag = temp;
+ /* discontinuity_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* cnt_dropped_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* n_frames */
+ BitstreamReadBits(stream, 8, &temp);
+
+
+ if (full_timestamp_flag)
+ {
+ /* seconds_value */
+ BitstreamReadBits(stream, 6, &temp);
+ /* minutes_value */
+ BitstreamReadBits(stream, 6, &temp);
+ /* hours_value */
+ BitstreamReadBits(stream, 5, &temp);
+ }
+ else
+ {
+ /* seconds_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* seconds_value */
+ BitstreamReadBits(stream, 6, &temp);
+ /* minutes_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* minutes_value */
+ BitstreamReadBits(stream, 6, &temp);
+
+ /* hourss_flag */
+ BitstreamRead1Bit(stream, &temp);
+
+ if (temp)
+ {
+ /* hours_value */
+ BitstreamReadBits(stream, 5, &temp);
+ }
+
+ }
+ }
+ }
+
+ if (time_offset_length)
+ {
+ /* time_offset */
+ BitstreamReadBits(stream, time_offset_length, &temp);
+ }
+ else
+ {
+ /* time_offset */
+ temp = 0;
+ }
+ }
+ }
+ }
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status recovery_point(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ OSCL_UNUSED_ARG(decvid);
+ uint temp;
+ /* recover_frame_cnt */
+ ue_v(stream, &temp);
+ /* exact_match_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* broken_link_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* changing slic_group_idc */
+ BitstreamReadBits(stream, 2, &temp);
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status dec_ref_pic_marking_repetition(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ AVCSeqParamSet *currSPS;
+ uint temp;
+ currSPS = decvid->seqParams[decvid->common->seq_parameter_set_id];
+ /* original_idr_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* original_frame_num */
+ ue_v(stream, &temp);
+ if (currSPS->frame_mbs_only_flag == 0)
+ {
+ /* original_field_pic_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* original_bottom_field_flag */
+ BitstreamRead1Bit(stream, &temp);
+ }
+ }
+
+ /* dec_ref_pic_marking(video,stream,sliceHdr); */
+
+
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status motion_constrained_slice_group_set(AVCDecObject *decvid, AVCDecBitstream *stream)
+{
+ OSCL_UNUSED_ARG(decvid);
+ uint temp, i, numBits;
+ /* num_slice_groups_in_set_minus1 */
+ ue_v(stream, &temp);
+
+ numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
+ i = temp;
+ while (i > 0)
+ {
+ numBits++;
+ i >>= 1;
+ }
+ for (i = 0; i <= temp; i++)
+ {
+ /* slice_group_id */
+ BitstreamReadBits(stream, numBits, &temp);
+ }
+ /* exact_sample_value_match_flag */
+ BitstreamRead1Bit(stream, &temp);
+ /* pan_scan_rect_flag */
+ BitstreamRead1Bit(stream, &temp);
+ if (temp)
+ {
+ /* pan_scan_rect_id */
+ ue_v(stream, &temp);
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/dec/src/itrans.cpp b/media/libstagefright/codecs/avc/dec/src/itrans.cpp
new file mode 100644
index 0000000..02c550d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/itrans.cpp
@@ -0,0 +1,307 @@
+/* ------------------------------------------------------------------
+ * 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 "avclib_common.h"
+
+/* input are in the first 16 elements of block,
+ output must be in the location specified in Figure 8-6. */
+/* subclause 8.5.6 */
+void Intra16DCTrans(int16 *block, int Qq, int Rq)
+{
+ int m0, m1, m2, m3;
+ int j, offset;
+ int16 *inout;
+ int scale = dequant_coefres[Rq][0];
+
+ inout = block;
+ for (j = 0; j < 4; j++)
+ {
+ m0 = inout[0] + inout[4];
+ m1 = inout[0] - inout[4];
+ m2 = inout[8] + inout[12];
+ m3 = inout[8] - inout[12];
+
+
+ inout[0] = m0 + m2;
+ inout[4] = m0 - m2;
+ inout[8] = m1 - m3;
+ inout[12] = m1 + m3;
+ inout += 64;
+ }
+
+ inout = block;
+
+ if (Qq >= 2) /* this way should be faster than JM */
+ { /* they use (((m4*scale)<<(QPy/6))+2)>>2 for both cases. */
+ Qq -= 2;
+ for (j = 0; j < 4; j++)
+ {
+ m0 = inout[0] + inout[64];
+ m1 = inout[0] - inout[64];
+ m2 = inout[128] + inout[192];
+ m3 = inout[128] - inout[192];
+
+ inout[0] = ((m0 + m2) * scale) << Qq;
+ inout[64] = ((m0 - m2) * scale) << Qq;
+ inout[128] = ((m1 - m3) * scale) << Qq;
+ inout[192] = ((m1 + m3) * scale) << Qq;
+ inout += 4;
+ }
+ }
+ else
+ {
+ Qq = 2 - Qq;
+ offset = 1 << (Qq - 1);
+
+ for (j = 0; j < 4; j++)
+ {
+ m0 = inout[0] + inout[64];
+ m1 = inout[0] - inout[64];
+ m2 = inout[128] + inout[192];
+ m3 = inout[128] - inout[192];
+
+ inout[0] = (((m0 + m2) * scale + offset) >> Qq);
+ inout[64] = (((m0 - m2) * scale + offset) >> Qq);
+ inout[128] = (((m1 - m3) * scale + offset) >> Qq);
+ inout[192] = (((m1 + m3) * scale + offset) >> Qq);
+ inout += 4;
+ }
+ }
+
+ return ;
+}
+
+/* see subclase 8.5.8 */
+void itrans(int16 *block, uint8 *pred, uint8 *cur, int width)
+{
+ int e0, e1, e2, e3; /* note, at every step of the calculation, these values */
+ /* shall never exceed 16bit sign value, but we don't check */
+ int i; /* to save the cycles. */
+ int16 *inout;
+
+ inout = block;
+
+ for (i = 4; i > 0; i--)
+ {
+ e0 = inout[0] + inout[2];
+ e1 = inout[0] - inout[2];
+ e2 = (inout[1] >> 1) - inout[3];
+ e3 = inout[1] + (inout[3] >> 1);
+
+ inout[0] = e0 + e3;
+ inout[1] = e1 + e2;
+ inout[2] = e1 - e2;
+ inout[3] = e0 - e3;
+
+ inout += 16;
+ }
+
+ for (i = 4; i > 0; i--)
+ {
+ e0 = block[0] + block[32];
+ e1 = block[0] - block[32];
+ e2 = (block[16] >> 1) - block[48];
+ e3 = block[16] + (block[48] >> 1);
+
+ e0 += e3;
+ e3 = (e0 - (e3 << 1)); /* e0-e3 */
+ e1 += e2;
+ e2 = (e1 - (e2 << 1)); /* e1-e2 */
+ e0 += 32;
+ e1 += 32;
+ e2 += 32;
+ e3 += 32;
+#ifdef USE_PRED_BLOCK
+ e0 = pred[0] + (e0 >> 6);
+ if ((uint)e0 > 0xFF) e0 = 0xFF & (~(e0 >> 31)); /* clip */
+ e1 = pred[20] + (e1 >> 6);
+ if ((uint)e1 > 0xFF) e1 = 0xFF & (~(e1 >> 31)); /* clip */
+ e2 = pred[40] + (e2 >> 6);
+ if ((uint)e2 > 0xFF) e2 = 0xFF & (~(e2 >> 31)); /* clip */
+ e3 = pred[60] + (e3 >> 6);
+ if ((uint)e3 > 0xFF) e3 = 0xFF & (~(e3 >> 31)); /* clip */
+ *cur = e0;
+ *(cur += width) = e1;
+ *(cur += width) = e2;
+ cur[width] = e3;
+ cur -= (width << 1);
+ cur++;
+ pred++;
+#else
+ OSCL_UNUSED_ARG(pred);
+
+ e0 = *cur + (e0 >> 6);
+ if ((uint)e0 > 0xFF) e0 = 0xFF & (~(e0 >> 31)); /* clip */
+ *cur = e0;
+ e1 = *(cur += width) + (e1 >> 6);
+ if ((uint)e1 > 0xFF) e1 = 0xFF & (~(e1 >> 31)); /* clip */
+ *cur = e1;
+ e2 = *(cur += width) + (e2 >> 6);
+ if ((uint)e2 > 0xFF) e2 = 0xFF & (~(e2 >> 31)); /* clip */
+ *cur = e2;
+ e3 = cur[width] + (e3 >> 6);
+ if ((uint)e3 > 0xFF) e3 = 0xFF & (~(e3 >> 31)); /* clip */
+ cur[width] = e3;
+ cur -= (width << 1);
+ cur++;
+#endif
+ block++;
+ }
+
+ return ;
+}
+
+/* see subclase 8.5.8 */
+void ictrans(int16 *block, uint8 *pred, uint8 *cur, int width)
+{
+ int e0, e1, e2, e3; /* note, at every step of the calculation, these values */
+ /* shall never exceed 16bit sign value, but we don't check */
+ int i; /* to save the cycles. */
+ int16 *inout;
+
+ inout = block;
+
+ for (i = 4; i > 0; i--)
+ {
+ e0 = inout[0] + inout[2];
+ e1 = inout[0] - inout[2];
+ e2 = (inout[1] >> 1) - inout[3];
+ e3 = inout[1] + (inout[3] >> 1);
+
+ inout[0] = e0 + e3;
+ inout[1] = e1 + e2;
+ inout[2] = e1 - e2;
+ inout[3] = e0 - e3;
+
+ inout += 16;
+ }
+
+ for (i = 4; i > 0; i--)
+ {
+ e0 = block[0] + block[32];
+ e1 = block[0] - block[32];
+ e2 = (block[16] >> 1) - block[48];
+ e3 = block[16] + (block[48] >> 1);
+
+ e0 += e3;
+ e3 = (e0 - (e3 << 1)); /* e0-e3 */
+ e1 += e2;
+ e2 = (e1 - (e2 << 1)); /* e1-e2 */
+ e0 += 32;
+ e1 += 32;
+ e2 += 32;
+ e3 += 32;
+#ifdef USE_PRED_BLOCK
+ e0 = pred[0] + (e0 >> 6);
+ if ((uint)e0 > 0xFF) e0 = 0xFF & (~(e0 >> 31)); /* clip */
+ e1 = pred[12] + (e1 >> 6);
+ if ((uint)e1 > 0xFF) e1 = 0xFF & (~(e1 >> 31)); /* clip */
+ e2 = pred[24] + (e2 >> 6);
+ if ((uint)e2 > 0xFF) e2 = 0xFF & (~(e2 >> 31)); /* clip */
+ e3 = pred[36] + (e3 >> 6);
+ if ((uint)e3 > 0xFF) e3 = 0xFF & (~(e3 >> 31)); /* clip */
+ *cur = e0;
+ *(cur += width) = e1;
+ *(cur += width) = e2;
+ cur[width] = e3;
+ cur -= (width << 1);
+ cur++;
+ pred++;
+#else
+ OSCL_UNUSED_ARG(pred);
+
+ e0 = *cur + (e0 >> 6);
+ if ((uint)e0 > 0xFF) e0 = 0xFF & (~(e0 >> 31)); /* clip */
+ *cur = e0;
+ e1 = *(cur += width) + (e1 >> 6);
+ if ((uint)e1 > 0xFF) e1 = 0xFF & (~(e1 >> 31)); /* clip */
+ *cur = e1;
+ e2 = *(cur += width) + (e2 >> 6);
+ if ((uint)e2 > 0xFF) e2 = 0xFF & (~(e2 >> 31)); /* clip */
+ *cur = e2;
+ e3 = cur[width] + (e3 >> 6);
+ if ((uint)e3 > 0xFF) e3 = 0xFF & (~(e3 >> 31)); /* clip */
+ cur[width] = e3;
+ cur -= (width << 1);
+ cur++;
+#endif
+ block++;
+ }
+
+ return ;
+}
+
+/* see subclause 8.5.7 */
+void ChromaDCTrans(int16 *block, int Qq, int Rq)
+{
+ int c00, c01, c10, c11;
+ int f0, f1, f2, f3;
+ int scale = dequant_coefres[Rq][0];
+
+ c00 = block[0] + block[4];
+ c01 = block[0] - block[4];
+ c10 = block[64] + block[68];
+ c11 = block[64] - block[68];
+
+ f0 = c00 + c10;
+ f1 = c01 + c11;
+ f2 = c00 - c10;
+ f3 = c01 - c11;
+
+ if (Qq >= 1)
+ {
+ Qq -= 1;
+ block[0] = (f0 * scale) << Qq;
+ block[4] = (f1 * scale) << Qq;
+ block[64] = (f2 * scale) << Qq;
+ block[68] = (f3 * scale) << Qq;
+ }
+ else
+ {
+ block[0] = (f0 * scale) >> 1;
+ block[4] = (f1 * scale) >> 1;
+ block[64] = (f2 * scale) >> 1;
+ block[68] = (f3 * scale) >> 1;
+ }
+
+ return ;
+}
+
+
+void copy_block(uint8 *pred, uint8 *cur, int width, int pred_pitch)
+{
+ uint32 temp;
+
+ temp = *((uint32*)pred);
+ pred += pred_pitch;
+ *((uint32*)cur) = temp;
+ cur += width;
+ temp = *((uint32*)pred);
+ pred += pred_pitch;
+ *((uint32*)cur) = temp;
+ cur += width;
+ temp = *((uint32*)pred);
+ pred += pred_pitch;
+ *((uint32*)cur) = temp;
+ cur += width;
+ temp = *((uint32*)pred);
+ *((uint32*)cur) = temp;
+
+ return ;
+}
+
+
diff --git a/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp b/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp
new file mode 100644
index 0000000..ba36c37
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp
@@ -0,0 +1,2329 @@
+/* ------------------------------------------------------------------
+ * 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 "avcdec_lib.h"
+
+
+#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
+ x = 0xFF & (~(x>>31));}
+
+/* (blkwidth << 2) + (dy << 1) + dx */
+static void (*const ChromaMC_SIMD[8])(uint8 *, int , int , int , uint8 *, int, int , int) =
+{
+ &ChromaFullMC_SIMD,
+ &ChromaHorizontalMC_SIMD,
+ &ChromaVerticalMC_SIMD,
+ &ChromaDiagonalMC_SIMD,
+ &ChromaFullMC_SIMD,
+ &ChromaHorizontalMC2_SIMD,
+ &ChromaVerticalMC2_SIMD,
+ &ChromaDiagonalMC2_SIMD
+};
+/* Perform motion prediction and compensation with residue if exist. */
+void InterMBPrediction(AVCCommonObj *video)
+{
+ AVCMacroblock *currMB = video->currMB;
+ AVCPictureData *currPic = video->currPic;
+ int mbPartIdx, subMbPartIdx;
+ int ref_idx;
+ int offset_MbPart_indx = 0;
+ int16 *mv;
+ uint32 x_pos, y_pos;
+ uint8 *curL, *curCb, *curCr;
+ uint8 *ref_l, *ref_Cb, *ref_Cr;
+ uint8 *predBlock, *predCb, *predCr;
+ int block_x, block_y, offset_x, offset_y, offsetP, offset;
+ int x_position = (video->mb_x << 4);
+ int y_position = (video->mb_y << 4);
+ int MbHeight, MbWidth, mbPartIdx_X, mbPartIdx_Y, offset_indx;
+ int picWidth = currPic->pitch;
+ int picHeight = currPic->height;
+ int16 *dataBlock;
+ uint32 cbp4x4;
+ uint32 tmp_word;
+
+ tmp_word = y_position * picWidth;
+ curL = currPic->Sl + tmp_word + x_position;
+ offset = (tmp_word >> 2) + (x_position >> 1);
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+
+#ifdef USE_PRED_BLOCK
+ predBlock = video->pred + 84;
+ predCb = video->pred + 452;
+ predCr = video->pred + 596;
+#else
+ predBlock = curL;
+ predCb = curCb;
+ predCr = curCr;
+#endif
+
+ GetMotionVectorPredictor(video, false);
+
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ MbHeight = currMB->SubMbPartHeight[mbPartIdx];
+ MbWidth = currMB->SubMbPartWidth[mbPartIdx];
+ mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1);
+ mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) >> 1;
+ ref_idx = currMB->ref_idx_L0[(mbPartIdx_Y << 1) + mbPartIdx_X];
+ offset_indx = 0;
+
+ ref_l = video->RefPicList0[ref_idx]->Sl;
+ ref_Cb = video->RefPicList0[ref_idx]->Scb;
+ ref_Cr = video->RefPicList0[ref_idx]->Scr;
+
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ block_x = (mbPartIdx_X << 1) + ((subMbPartIdx + offset_indx) & 1); // check this
+ block_y = (mbPartIdx_Y << 1) + (((subMbPartIdx + offset_indx) >> 1) & 1);
+ mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+ offset_x = x_position + (block_x << 2);
+ offset_y = y_position + (block_y << 2);
+ x_pos = (offset_x << 2) + *mv++; /*quarter pel */
+ y_pos = (offset_y << 2) + *mv; /*quarter pel */
+
+ //offset = offset_y * currPic->width;
+ //offsetC = (offset >> 2) + (offset_x >> 1);
+#ifdef USE_PRED_BLOCK
+ offsetP = (block_y * 80) + (block_x << 2);
+ LumaMotionComp(ref_l, picWidth, picHeight, x_pos, y_pos,
+ /*comp_Sl + offset + offset_x,*/
+ predBlock + offsetP, 20, MbWidth, MbHeight);
+#else
+ offsetP = (block_y << 2) * picWidth + (block_x << 2);
+ LumaMotionComp(ref_l, picWidth, picHeight, x_pos, y_pos,
+ /*comp_Sl + offset + offset_x,*/
+ predBlock + offsetP, picWidth, MbWidth, MbHeight);
+#endif
+
+#ifdef USE_PRED_BLOCK
+ offsetP = (block_y * 24) + (block_x << 1);
+ ChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scb + offsetC,*/
+ predCb + offsetP, 12, MbWidth >> 1, MbHeight >> 1);
+ ChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scr + offsetC,*/
+ predCr + offsetP, 12, MbWidth >> 1, MbHeight >> 1);
+#else
+ offsetP = (block_y * picWidth) + (block_x << 1);
+ ChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scb + offsetC,*/
+ predCb + offsetP, picWidth >> 1, MbWidth >> 1, MbHeight >> 1);
+ ChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scr + offsetC,*/
+ predCr + offsetP, picWidth >> 1, MbWidth >> 1, MbHeight >> 1);
+#endif
+
+ offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+ }
+ offset_MbPart_indx = currMB->MbPartWidth >> 4;
+ }
+
+ /* used in decoder, used to be if(!encFlag) */
+
+ /* transform in raster scan order */
+ dataBlock = video->block;
+ cbp4x4 = video->cbp4x4;
+ /* luma */
+ for (block_y = 4; block_y > 0; block_y--)
+ {
+ for (block_x = 4; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ itrans(dataBlock, predBlock, predBlock, 20);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ itrans(dataBlock, curL, curL, picWidth);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ predBlock += 4;
+#else
+ curL += 4;
+#endif
+ }
+ dataBlock += 48;
+#ifdef USE_PRED_BLOCK
+ predBlock += 64;
+#else
+ curL += ((picWidth << 2) - 16);
+#endif
+ }
+
+ /* chroma */
+ picWidth = (picWidth >> 1);
+ for (block_y = 2; block_y > 0; block_y--)
+ {
+ for (block_x = 2; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, predCb, predCb, 12);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, curCb, curCb, picWidth);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ predCb += 4;
+#else
+ curCb += 4;
+#endif
+ }
+ for (block_x = 2; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, predCr, predCr, 12);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, curCr, curCr, picWidth);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ predCr += 4;
+#else
+ curCr += 4;
+#endif
+ }
+ dataBlock += 48;
+#ifdef USE_PRED_BLOCK
+ predCb += 40;
+ predCr += 40;
+#else
+ curCb += ((picWidth << 2) - 8);
+ curCr += ((picWidth << 2) - 8);
+#endif
+ }
+
+#ifdef MB_BASED_DEBLOCK
+ SaveNeighborForIntraPred(video, offset);
+#endif
+
+ return ;
+}
+
+
+/* preform the actual motion comp here */
+void LumaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight)
+{
+ int dx, dy;
+ uint8 temp[24][24]; /* for padding, make the size multiple of 4 for packing */
+ int temp2[21][21]; /* for intermediate results */
+ uint8 *ref2;
+
+ dx = x_pos & 3;
+ dy = y_pos & 3;
+ x_pos = x_pos >> 2; /* round it to full-pel resolution */
+ y_pos = y_pos >> 2;
+
+ /* perform actual motion compensation */
+ if (dx == 0 && dy == 0)
+ { /* fullpel position *//* G */
+ if (x_pos >= 0 && x_pos + blkwidth <= picwidth && y_pos >= 0 && y_pos + blkheight <= picheight)
+ {
+ ref += y_pos * picwidth + x_pos;
+ FullPelMC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight);
+ }
+ else
+ {
+ CreatePad(ref, picwidth, picheight, x_pos, y_pos, &temp[0][0], blkwidth, blkheight);
+ FullPelMC(&temp[0][0], 24, pred, pred_pitch, blkwidth, blkheight);
+ }
+
+ } /* other positions */
+ else if (dy == 0)
+ { /* no vertical interpolation *//* a,b,c*/
+
+ if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos >= 0 && y_pos + blkheight <= picheight)
+ {
+ ref += y_pos * picwidth + x_pos;
+
+ HorzInterp1MC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ else /* need padding */
+ {
+ CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos, &temp[0][0], blkwidth + 5, blkheight);
+
+ HorzInterp1MC(&temp[0][2], 24, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ }
+ else if (dx == 0)
+ { /*no horizontal interpolation *//* d,h,n */
+
+ if (x_pos >= 0 && x_pos + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
+ {
+ ref += y_pos * picwidth + x_pos;
+
+ VertInterp1MC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ else /* need padding */
+ {
+ CreatePad(ref, picwidth, picheight, x_pos, y_pos - 2, &temp[0][0], blkwidth, blkheight + 5);
+
+ VertInterp1MC(&temp[2][0], 24, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ }
+ else if (dy == 2)
+ { /* horizontal cross *//* i, j, k */
+
+ if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
+ {
+ ref += y_pos * picwidth + x_pos - 2; /* move to the left 2 pixels */
+
+ VertInterp2MC(ref, picwidth, &temp2[0][0], 21, blkwidth + 5, blkheight);
+
+ HorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ else /* need padding */
+ {
+ CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5, blkheight + 5);
+
+ VertInterp2MC(&temp[2][0], 24, &temp2[0][0], 21, blkwidth + 5, blkheight);
+
+ HorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ }
+ else if (dx == 2)
+ { /* vertical cross */ /* f,q */
+
+ if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
+ {
+ ref += (y_pos - 2) * picwidth + x_pos; /* move to up 2 lines */
+
+ HorzInterp3MC(ref, picwidth, &temp2[0][0], 21, blkwidth, blkheight + 5);
+ VertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ else /* need padding */
+ {
+ CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5, blkheight + 5);
+ HorzInterp3MC(&temp[0][2], 24, &temp2[0][0], 21, blkwidth, blkheight + 5);
+ VertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ }
+ else
+ { /* diagonal *//* e,g,p,r */
+
+ if (x_pos - 2 >= 0 && x_pos + 3 + (dx / 2) + blkwidth <= picwidth &&
+ y_pos - 2 >= 0 && y_pos + 3 + blkheight + (dy / 2) <= picheight)
+ {
+ ref2 = ref + (y_pos + (dy / 2)) * picwidth + x_pos;
+
+ ref += (y_pos * picwidth) + x_pos + (dx / 2);
+
+ DiagonalInterpMC(ref2, ref, picwidth, pred, pred_pitch, blkwidth, blkheight);
+ }
+ else /* need padding */
+ {
+ CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5 + (dx / 2), blkheight + 5 + (dy / 2));
+
+ ref2 = &temp[2 + (dy/2)][2];
+
+ ref = &temp[2][2 + (dx/2)];
+
+ DiagonalInterpMC(ref2, ref, 24, pred, pred_pitch, blkwidth, blkheight);
+ }
+ }
+
+ return ;
+}
+
+void CreateAlign(uint8 *ref, int picwidth, int y_pos,
+ uint8 *out, int blkwidth, int blkheight)
+{
+ int i, j;
+ int offset, out_offset;
+ uint32 prev_pix, result, pix1, pix2, pix4;
+
+ out_offset = 24 - blkwidth;
+
+ //switch(x_pos&0x3){
+ switch (((uint32)ref)&0x3)
+ {
+ case 1:
+ ref += y_pos * picwidth;
+ offset = picwidth - blkwidth - 3;
+ for (j = 0; j < blkheight; j++)
+ {
+ pix1 = *ref++;
+ pix2 = *((uint16*)ref);
+ ref += 2;
+ result = (pix2 << 8) | pix1;
+
+ for (i = 3; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 24) & 0xFF000000; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 8; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ case 2:
+ ref += y_pos * picwidth;
+ offset = picwidth - blkwidth - 2;
+ for (j = 0; j < blkheight; j++)
+ {
+ result = *((uint16*)ref);
+ ref += 2;
+ for (i = 2; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 16) & 0xFFFF0000; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 16; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ case 3:
+ ref += y_pos * picwidth;
+ offset = picwidth - blkwidth - 1;
+ for (j = 0; j < blkheight; j++)
+ {
+ result = *ref++;
+ for (i = 1; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 8) & 0xFFFFFF00; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 24; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ }
+}
+
+void CreatePad(uint8 *ref, int picwidth, int picheight, int x_pos, int y_pos,
+ uint8 *out, int blkwidth, int blkheight)
+{
+ int x_inc0, x_mid;
+ int y_inc, y_inc0, y_inc1, y_mid;
+ int i, j;
+ int offset;
+
+ if (x_pos < 0)
+ {
+ x_inc0 = 0; /* increment for the first part */
+ x_mid = ((blkwidth + x_pos > 0) ? -x_pos : blkwidth); /* stopping point */
+ x_pos = 0;
+ }
+ else if (x_pos + blkwidth > picwidth)
+ {
+ x_inc0 = 1; /* increasing */
+ x_mid = ((picwidth > x_pos) ? picwidth - x_pos - 1 : 0); /* clip negative to zero, encode fool proof! */
+ }
+ else /* normal case */
+ {
+ x_inc0 = 1;
+ x_mid = blkwidth; /* just one run */
+ }
+
+
+ /* boundary for y_pos, taking the result from x_pos into account */
+ if (y_pos < 0)
+ {
+ y_inc0 = (x_inc0 ? - x_mid : -blkwidth + x_mid); /* offset depending on x_inc1 and x_inc0 */
+ y_inc1 = picwidth + y_inc0;
+ y_mid = ((blkheight + y_pos > 0) ? -y_pos : blkheight); /* clip to prevent memory corruption */
+ y_pos = 0;
+ }
+ else if (y_pos + blkheight > picheight)
+ {
+ y_inc1 = (x_inc0 ? - x_mid : -blkwidth + x_mid); /* saturate */
+ y_inc0 = picwidth + y_inc1; /* increasing */
+ y_mid = ((picheight > y_pos) ? picheight - 1 - y_pos : 0);
+ }
+ else /* normal case */
+ {
+ y_inc1 = (x_inc0 ? - x_mid : -blkwidth + x_mid);
+ y_inc0 = picwidth + y_inc1;
+ y_mid = blkheight;
+ }
+
+ /* clip y_pos and x_pos */
+ if (y_pos > picheight - 1) y_pos = picheight - 1;
+ if (x_pos > picwidth - 1) x_pos = picwidth - 1;
+
+ ref += y_pos * picwidth + x_pos;
+
+ y_inc = y_inc0; /* start with top half */
+
+ offset = 24 - blkwidth; /* to use in offset out */
+ blkwidth -= x_mid; /* to use in the loop limit */
+
+ if (x_inc0 == 0)
+ {
+ for (j = 0; j < blkheight; j++)
+ {
+ if (j == y_mid) /* put a check here to reduce the code size (for unrolling the loop) */
+ {
+ y_inc = y_inc1; /* switch to lower half */
+ }
+ for (i = x_mid; i > 0; i--) /* first or third quarter */
+ {
+ *out++ = *ref;
+ }
+ for (i = blkwidth; i > 0; i--) /* second or fourth quarter */
+ {
+ *out++ = *ref++;
+ }
+ out += offset;
+ ref += y_inc;
+ }
+ }
+ else
+ {
+ for (j = 0; j < blkheight; j++)
+ {
+ if (j == y_mid) /* put a check here to reduce the code size (for unrolling the loop) */
+ {
+ y_inc = y_inc1; /* switch to lower half */
+ }
+ for (i = x_mid; i > 0; i--) /* first or third quarter */
+ {
+ *out++ = *ref++;
+ }
+ for (i = blkwidth; i > 0; i--) /* second or fourth quarter */
+ {
+ *out++ = *ref;
+ }
+ out += offset;
+ ref += y_inc;
+ }
+ }
+
+ return ;
+}
+
+void HorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx)
+{
+ uint8 *p_ref;
+ uint32 *p_cur;
+ uint32 tmp, pkres;
+ int result, curr_offset, ref_offset;
+ int j;
+ int32 r0, r1, r2, r3, r4, r5;
+ int32 r13, r6;
+
+ p_cur = (uint32*)out; /* assume it's word aligned */
+ curr_offset = (outpitch - blkwidth) >> 2;
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ if (dx&1)
+ {
+ dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+ p_ref -= 2;
+ r13 = 0;
+ for (j = blkheight; j > 0; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+ while ((uint32)p_ref < tmp)
+ {
+ r2 = *(p_ref += 4); /* move pointer to e */
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+
+ r5 = p_ref[dx+2];
+ r6 = p_ref[dx+4];
+ r5 |= (r6 << 16);
+ r4 += r5;
+ r4 += 0x10001;
+ r4 = (r4 >> 1) & 0xFF00FF;
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+
+ r0 = p_ref[dx+3];
+ r1 = p_ref[dx+5];
+ r0 |= (r1 << 16);
+ r5 += r0;
+ r5 += 0x10001;
+ r5 = (r5 >> 1) & 0xFF00FF;
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_cur++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_cur -= (outpitch >> 2);
+
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ pkres = (result >> 1) ;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 5; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+ }
+ else
+ {
+ p_ref -= 2;
+ r13 = 0;
+ for (j = blkheight; j > 0; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+ while ((uint32)p_ref < tmp)
+ {
+ r2 = *(p_ref += 4); /* move pointer to e */
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+ r4 &= 0xFF00FF; /* mask */
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+ r5 &= 0xFF00FF; /* mask */
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_cur++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_cur -= (outpitch >> 2);
+
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 5;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset;
+ }
+ }
+ }
+
+ return ;
+}
+
+void HorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx)
+{
+ int *p_ref;
+ uint32 *p_cur;
+ uint32 tmp, pkres;
+ int result, result2, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = (uint32*)out; /* assume it's word aligned */
+ curr_offset = (outpitch - blkwidth) >> 2;
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ if (dx&1)
+ {
+ dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ pkres = (result >> 1);
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 3; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 3; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+
+ return ;
+}
+
+void HorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ uint8 *p_ref;
+ int *p_cur;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = (outpitch - blkwidth);
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ *p_cur++ = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ *p_cur++ = result;
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ *p_cur++ = result;
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ *p_cur++ = result;
+ p_ref -= 3; /* move back to the middle of the filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset;
+ }
+
+ return ;
+}
+void VertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy)
+{
+ uint8 *p_cur, *p_ref;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, i;
+ int32 r0, r1, r2, r3, r4, r5, r6, r7, r8, r13;
+ uint8 tmp_in[24][24];
+
+ /* not word-aligned */
+ if (((uint32)in)&0x3)
+ {
+ CreateAlign(in, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+ in = &tmp_in[2][0];
+ inpitch = 24;
+ }
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ curr_offset += 3;
+
+ if (dy&1)
+ {
+ dy = (dy >> 1) ? 0 : -inpitch;
+
+ for (j = 0; j < blkwidth; j += 4, in += 4)
+ {
+ r13 = 0;
+ p_ref = in;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+
+ r1 = *((uint32*)(p_ref + dy));
+ r2 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r0 += r1;
+ r6 += r2;
+ r0 += 0x10001;
+ r6 += 0x10001;
+ r0 = (r0 >> 1) & 0xFF00FF;
+ r6 = (r6 >> 1) & 0xFF00FF;
+
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in + i;
+ p_cur -= outpitch; /* compensate for the first offset */
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (j = 0; j < blkwidth; j += 4, in += 4)
+ {
+ r13 = 0;
+ p_ref = in;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+ r0 &= 0xFF00FF;
+ r6 &= 0xFF00FF;
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in + i;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+ }
+
+ return ;
+}
+
+void VertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int *p_cur;
+ uint8 *p_ref;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+
+ return ;
+}
+
+void VertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy)
+{
+ uint8 *p_cur;
+ int *p_ref;
+ uint32 tmp;
+ int result, result2, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ if (dy&1)
+ {
+ dy = (dy >> 1) ? -(inpitch << 1) : -(inpitch << 1) - inpitch;
+
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+ }
+ else
+ {
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+ }
+
+ return ;
+}
+
+void DiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+ uint8 *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int j, i;
+ int result;
+ uint8 *p_cur, *p_ref, *p_tmp8;
+ int curr_offset, ref_offset;
+ uint8 tmp_res[24][24], tmp_in[24][24];
+ uint32 *p_tmp;
+ uint32 tmp, pkres, tmp_result;
+ int32 r0, r1, r2, r3, r4, r5;
+ int32 r6, r7, r8, r9, r10, r13;
+
+ ref_offset = inpitch - blkwidth;
+ p_ref = in1 - 2;
+ /* perform horizontal interpolation */
+ /* not word-aligned */
+ /* It is faster to read 1 byte at time to avoid calling CreateAlign */
+ /* if(((uint32)p_ref)&0x3)
+ {
+ CreateAlign(p_ref,inpitch,0,&tmp_in[0][0],blkwidth+8,blkheight);
+ p_ref = &tmp_in[0][0];
+ ref_offset = 24-blkwidth;
+ }*/
+
+ p_tmp = (uint32*) & (tmp_res[0][0]);
+ for (j = blkheight; j > 0; j--)
+ {
+ r13 = 0;
+ tmp = (uint32)(p_ref + blkwidth);
+
+ //r0 = *((uint32*)p_ref); /* d,c,b,a */
+ //r1 = (r0>>8)&0xFF00FF; /* 0,d,0,b */
+ //r0 &= 0xFF00FF; /* 0,c,0,a */
+ /* It is faster to read 1 byte at a time, */
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+
+ while ((uint32)p_ref < tmp)
+ {
+ //r2 = *((uint32*)(p_ref+=4));/* h,g,f,e */
+ //r3 = (r2>>8)&0xFF00FF; /* 0,h,0,f */
+ //r2 &= 0xFF00FF; /* 0,g,0,e */
+ /* It is faster to read 1 byte at a time, */
+ r2 = *(p_ref += 4);
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+ r4 &= 0xFF00FF; /* mask */
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+ r5 &= 0xFF00FF; /* mask */
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_tmp++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_tmp -= 6; /* intermediate output */
+ tmp = (uint32)(p_ref + blkwidth);
+ while ((uint32)p_ref < tmp)
+ {
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+
+ *p_tmp++ = pkres; /* write 4 pixel */
+ p_ref -= 5;
+ }
+ p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+ }
+ }
+
+ /* perform vertical interpolation */
+ /* not word-aligned */
+ if (((uint32)in2)&0x3)
+ {
+ CreateAlign(in2, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+ in2 = &tmp_in[2][0];
+ inpitch = 24;
+ }
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically up and one pixel right */
+ pkres = blkheight * inpitch; /* reuse it for limit */
+
+ curr_offset += 3;
+
+ for (j = 0; j < blkwidth; j += 4, in2 += 4)
+ {
+ r13 = 0;
+ p_ref = in2;
+ p_tmp8 = &(tmp_res[0][j]); /* intermediate result */
+ p_tmp8 -= 24; /* compensate for the first offset */
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + pkres); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ /* Read 1 byte at a time is too slow, too many read and pack ops, need to call CreateAlign, */
+ /*p_ref8 = p_ref-(inpitch<<1); r0 = p_ref8[0]; r1 = p_ref8[2];
+ r0 |= (r1<<16); r6 = p_ref8[1]; r1 = p_ref8[3];
+ r6 |= (r1<<16); p_ref+=inpitch; */
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref+(inpitch<<1);
+ r1 = p_ref8[0]; r7 = p_ref8[2]; r1 |= (r7<<16);
+ r7 = p_ref8[1]; r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ /*r2 = p_ref[0]; r8 = p_ref[2]; r2 |= (r8<<16);
+ r8 = p_ref[1]; r1 = p_ref[3]; r8 |= (r1<<16);*/
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref-inpitch; r1 = p_ref8[0]; r7 = p_ref8[2];
+ r1 |= (r7<<16); r1 += r2; r7 = p_ref8[1];
+ r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ /*p_ref8 = p_ref-(inpitch<<1); r2 = p_ref8[0]; r8 = p_ref8[2];
+ r2 |= (r8<<16); r8 = p_ref8[1]; r1 = p_ref8[3]; r8 |= (r1<<16);*/
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref+inpitch; r1 = p_ref8[0]; r7 = p_ref8[2];
+ r1 |= (r7<<16); r1 += r2; r7 = p_ref8[1];
+ r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+ /* add with horizontal results */
+ r10 = *((uint32*)(p_tmp8 += 24));
+ r9 = (r10 >> 8) & 0xFF00FF;
+ r10 &= 0xFF00FF;
+
+ r0 += r10;
+ r0 += 0x10001;
+ r0 = (r0 >> 1) & 0xFF00FF; /* mask to 8 bytes */
+
+ r6 += r9;
+ r6 += 0x10001;
+ r6 = (r6 >> 1) & 0xFF00FF; /* mask to 8 bytes */
+
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in2 + i;
+ p_tmp8 = &(tmp_res[0][j+i]); /* intermediate result */
+ p_tmp8 -= 24; /* compensate for the first offset */
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + pkres); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* modify pointer before loading */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+
+ return ;
+}
+
+/* position G */
+void FullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int i, j;
+ int offset_in = inpitch - blkwidth;
+ int offset_out = outpitch - blkwidth;
+ uint32 temp;
+ uint8 byte;
+
+ if (((uint32)in)&3)
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 4)
+ {
+ temp = *in++;
+ byte = *in++;
+ temp |= (byte << 8);
+ byte = *in++;
+ temp |= (byte << 16);
+ byte = *in++;
+ temp |= (byte << 24);
+
+ *((uint32*)out) = temp; /* write 4 bytes */
+ out += 4;
+ }
+ out += offset_out;
+ in += offset_in;
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 4)
+ {
+ temp = *((uint32*)in);
+ *((uint32*)out) = temp;
+ in += 4;
+ out += 4;
+ }
+ out += offset_out;
+ in += offset_in;
+ }
+ }
+ return ;
+}
+
+void ChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight)
+{
+ int dx, dy;
+ int offset_dx, offset_dy;
+ int index;
+ uint8 temp[24][24];
+
+ dx = x_pos & 7;
+ dy = y_pos & 7;
+ offset_dx = (dx + 7) >> 3;
+ offset_dy = (dy + 7) >> 3;
+ x_pos = x_pos >> 3; /* round it to full-pel resolution */
+ y_pos = y_pos >> 3;
+
+ if ((x_pos >= 0 && x_pos + blkwidth + offset_dx <= picwidth) && (y_pos >= 0 && y_pos + blkheight + offset_dy <= picheight))
+ {
+ ref += y_pos * picwidth + x_pos;
+ }
+ else
+ {
+ CreatePad(ref, picwidth, picheight, x_pos, y_pos, &temp[0][0], blkwidth + offset_dx, blkheight + offset_dy);
+ ref = &temp[0][0];
+ picwidth = 24;
+ }
+
+ index = offset_dx + (offset_dy << 1) + ((blkwidth << 1) & 0x7);
+
+ (*(ChromaMC_SIMD[index]))(ref, picwidth , dx, dy, pred, pred_pitch, blkwidth, blkheight);
+ return ;
+}
+
+
+/* SIMD routines, unroll the loops in vertical direction, decreasing loops (things to be done) */
+void ChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ int32 r0, r1, r2, r3, result0, result1;
+ uint8 temp[288];
+ uint8 *ref, *out;
+ int i, j;
+ int dx_8 = 8 - dx;
+ int dy_8 = 8 - dy;
+
+ /* horizontal first */
+ out = temp;
+ for (i = 0; i < blkheight + 1; i++)
+ {
+ ref = pRef;
+ r0 = ref[0];
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 |= (ref[2] << 16);
+ result0 = dx_8 * r0;
+
+ r1 = ref[1] | (ref[3] << 16);
+ result0 += dx * r1;
+ *(int32 *)out = result0;
+
+ result0 = dx_8 * r1;
+
+ r2 = ref[4];
+ r0 = r0 >> 16;
+ r1 = r0 | (r2 << 16);
+ result0 += dx * r1;
+ *(int32 *)(out + 16) = result0;
+
+ ref += 4;
+ out += 4;
+ r0 = r2;
+ }
+ pRef += srcPitch;
+ out += (32 - blkwidth);
+ }
+
+// pRef -= srcPitch*(blkheight+1);
+ ref = temp;
+
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 = *(int32 *)ref;
+ r1 = *(int32 *)(ref + 16);
+ ref += 32;
+ out = pOut;
+ for (i = 0; i < (blkheight >> 1); i++)
+ {
+ result0 = dy_8 * r0 + 0x00200020;
+ r2 = *(int32 *)ref;
+ result0 += dy * r2;
+ result0 >>= 6;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00200020;
+ r3 = *(int32 *)(ref + 16);
+ result1 += dy * r3;
+ result1 >>= 6;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ out += predPitch;
+ ref += 32;
+
+ result0 = dy_8 * r0 + 0x00200020;
+ r2 = *(int32 *)ref;
+ result0 += dy * r2;
+ result0 >>= 6;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00200020;
+ r3 = *(int32 *)(ref + 16);
+ result1 += dy * r3;
+ result1 >>= 6;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ out += predPitch;
+ ref += 32;
+ }
+ pOut += 4;
+ ref = temp + 4; /* since it can only iterate twice max */
+ }
+ return;
+}
+
+void ChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(dy);
+ int32 r0, r1, r2, result0, result1;
+ uint8 *ref, *out;
+ int i, j;
+ int dx_8 = 8 - dx;
+
+ /* horizontal first */
+ for (i = 0; i < blkheight; i++)
+ {
+ ref = pRef;
+ out = pOut;
+
+ r0 = ref[0];
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 |= (ref[2] << 16);
+ result0 = dx_8 * r0 + 0x00040004;
+
+ r1 = ref[1] | (ref[3] << 16);
+ result0 += dx * r1;
+ result0 >>= 3;
+ result0 &= 0x00FF00FF;
+
+ result1 = dx_8 * r1 + 0x00040004;
+
+ r2 = ref[4];
+ r0 = r0 >> 16;
+ r1 = r0 | (r2 << 16);
+ result1 += dx * r1;
+ result1 >>= 3;
+ result1 &= 0x00FF00FF;
+
+ *(int32 *)out = result0 | (result1 << 8);
+
+ ref += 4;
+ out += 4;
+ r0 = r2;
+ }
+
+ pRef += srcPitch;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void ChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(dx);
+ int32 r0, r1, r2, r3, result0, result1;
+ int i, j;
+ uint8 *ref, *out;
+ int dy_8 = 8 - dy;
+ /* vertical first */
+ for (i = 0; i < blkwidth; i += 4)
+ {
+ ref = pRef;
+ out = pOut;
+
+ r0 = ref[0] | (ref[2] << 16);
+ r1 = ref[1] | (ref[3] << 16);
+ ref += srcPitch;
+ for (j = 0; j < blkheight; j++)
+ {
+ result0 = dy_8 * r0 + 0x00040004;
+ r2 = ref[0] | (ref[2] << 16);
+ result0 += dy * r2;
+ result0 >>= 3;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00040004;
+ r3 = ref[1] | (ref[3] << 16);
+ result1 += dy * r3;
+ result1 >>= 3;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ ref += srcPitch;
+ out += predPitch;
+ }
+ pOut += 4;
+ pRef += 4;
+ }
+ return;
+}
+
+void ChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(blkwidth);
+ int32 r0, r1, temp0, temp1, result;
+ int32 temp[9];
+ int32 *out;
+ int i, r_temp;
+ int dy_8 = 8 - dy;
+
+ /* horizontal first */
+ out = temp;
+ for (i = 0; i < blkheight + 1; i++)
+ {
+ r_temp = pRef[1];
+ temp0 = (pRef[0] << 3) + dx * (r_temp - pRef[0]);
+ temp1 = (r_temp << 3) + dx * (pRef[2] - r_temp);
+ r0 = temp0 | (temp1 << 16);
+ *out++ = r0;
+ pRef += srcPitch;
+ }
+
+ pRef -= srcPitch * (blkheight + 1);
+
+ out = temp;
+
+ r0 = *out++;
+
+ for (i = 0; i < blkheight; i++)
+ {
+ result = dy_8 * r0 + 0x00200020;
+ r1 = *out++;
+ result += dy * r1;
+ result >>= 6;
+ result &= 0x00FF00FF;
+ *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+ r0 = r1;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void ChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(dy);
+ OSCL_UNUSED_ARG(blkwidth);
+ int i, temp, temp0, temp1;
+
+ /* horizontal first */
+ for (i = 0; i < blkheight; i++)
+ {
+ temp = pRef[1];
+ temp0 = ((pRef[0] << 3) + dx * (temp - pRef[0]) + 4) >> 3;
+ temp1 = ((temp << 3) + dx * (pRef[2] - temp) + 4) >> 3;
+
+ *(int16 *)pOut = temp0 | (temp1 << 8);
+ pRef += srcPitch;
+ pOut += predPitch;
+
+ }
+ return;
+}
+void ChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(dx);
+ OSCL_UNUSED_ARG(blkwidth);
+ int32 r0, r1, result;
+ int i;
+ int dy_8 = 8 - dy;
+ r0 = pRef[0] | (pRef[1] << 16);
+ pRef += srcPitch;
+ for (i = 0; i < blkheight; i++)
+ {
+ result = dy_8 * r0 + 0x00040004;
+ r1 = pRef[0] | (pRef[1] << 16);
+ result += dy * r1;
+ result >>= 3;
+ result &= 0x00FF00FF;
+ *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+ r0 = r1;
+ pRef += srcPitch;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void ChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ OSCL_UNUSED_ARG(dx);
+ OSCL_UNUSED_ARG(dy);
+ int i, j;
+ int offset_in = srcPitch - blkwidth;
+ int offset_out = predPitch - blkwidth;
+ uint16 temp;
+ uint8 byte;
+
+ if (((uint32)pRef)&1)
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 2)
+ {
+ temp = *pRef++;
+ byte = *pRef++;
+ temp |= (byte << 8);
+ *((uint16*)pOut) = temp; /* write 2 bytes */
+ pOut += 2;
+ }
+ pOut += offset_out;
+ pRef += offset_in;
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 2)
+ {
+ temp = *((uint16*)pRef);
+ *((uint16*)pOut) = temp;
+ pRef += 2;
+ pOut += 2;
+ }
+ pOut += offset_out;
+ pRef += offset_in;
+ }
+ }
+ return ;
+}
diff --git a/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp b/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp
new file mode 100644
index 0000000..0b613a4
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp
@@ -0,0 +1,1786 @@
+/* ------------------------------------------------------------------
+ * 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 "avcdec_lib.h"
+
+#define CLIP_COMP *comp++ = (uint8)(((uint)temp>0xFF)? 0xFF&(~(temp>>31)): temp)
+#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
+ x = 0xFF & (~(x>>31));}
+
+
+/* We should combine the Intra4x4 functions with residual decoding and compensation */
+AVCStatus IntraMBPrediction(AVCCommonObj *video)
+{
+ int component, SubBlock_indx, temp;
+ AVCStatus status;
+ AVCMacroblock *currMB = video->currMB;
+ AVCPictureData *currPic = video->currPic;
+ uint8 *curL, *curCb, *curCr;
+ uint8 *comp;
+ int block_x, block_y, offset;
+ int16 *dataBlock = video->block;
+ uint8 *predCb, *predCr;
+#ifdef USE_PRED_BLOCK
+ uint8 *pred;
+#endif
+ int pitch = currPic->pitch;
+ uint32 cbp4x4 = video->cbp4x4;
+
+ offset = (video->mb_y << 4) * pitch + (video->mb_x << 4);
+ curL = currPic->Sl + offset;
+
+#ifdef USE_PRED_BLOCK
+ video->pred_block = video->pred + 84; /* point to separate prediction memory */
+ pred = video->pred_block;
+ video->pred_pitch = 20;
+#else
+ video->pred_block = curL; /* point directly to the frame buffer */
+ video->pred_pitch = pitch;
+#endif
+
+ if (currMB->mbMode == AVC_I4)
+ {
+ /* luminance first */
+ block_x = block_y = 0;
+ for (component = 0; component < 4; component++)
+ {
+ block_x = ((component & 1) << 1);
+ block_y = ((component >> 1) << 1);
+ comp = curL;// + (block_x<<2) + (block_y<<2)*currPic->pitch;
+
+ for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++)
+ {
+ status = Intra_4x4(video, block_x, block_y, comp);
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ /* transform following the 4x4 prediction, can't be SIMD
+ with other blocks. */
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&(1 << ((block_y << 2) + block_x)))
+ {
+ itrans(dataBlock, pred, pred, 20);
+ }
+#else
+ if (cbp4x4&(1 << ((block_y << 2) + block_x)))
+ {
+ itrans(dataBlock, comp, comp, pitch);
+ }
+#endif
+ temp = SubBlock_indx & 1;
+ if (temp)
+ {
+ block_y++;
+ block_x--;
+ dataBlock += 60;
+#ifdef USE_PRED_BLOCK
+ pred += 76;
+#else
+ comp += ((pitch << 2) - 4);
+#endif
+ }
+ else
+ {
+ block_x++;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ pred += 4;
+#else
+ comp += 4;
+#endif
+ }
+ }
+ if (component&1)
+ {
+#ifdef USE_PRED_BLOCK
+ pred -= 8;
+#else
+ curL += (pitch << 3) - 8;
+#endif
+ dataBlock -= 8;
+ }
+ else
+ {
+#ifdef USE_PRED_BLOCK
+ pred -= 152;
+#else
+ curL += 8;
+#endif
+ dataBlock -= 120;
+ }
+ }
+ cbp4x4 >>= 16;
+ }
+ else /* AVC_I16 */
+ {
+#ifdef MB_BASED_DEBLOCK
+ video->pintra_pred_top = video->intra_pred_top + (video->mb_x << 4);
+ video->pintra_pred_left = video->intra_pred_left + 1;
+ video->intra_pred_topleft = video->intra_pred_left[0];
+ pitch = 1;
+#else
+ video->pintra_pred_top = curL - pitch;
+ video->pintra_pred_left = curL - 1;
+ if (video->mb_y)
+ {
+ video->intra_pred_topleft = *(curL - pitch - 1);
+ }
+#endif
+ switch (currMB->i16Mode)
+ {
+ case AVC_I16_Vertical: /* Intra_16x16_Vertical */
+ /* check availability of top */
+ if (video->intraAvailB)
+ {
+ Intra_16x16_Vertical(video);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ case AVC_I16_Horizontal: /* Intra_16x16_Horizontal */
+ /* check availability of left */
+ if (video->intraAvailA)
+ {
+ Intra_16x16_Horizontal(video, pitch);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ case AVC_I16_DC: /* Intra_16x16_DC */
+ Intra_16x16_DC(video, pitch);
+ break;
+ case AVC_I16_Plane: /* Intra_16x16_Plane */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ Intra_16x16_Plane(video, pitch);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ pitch = currPic->pitch;
+
+ /* transform */
+ /* can go in raster scan order now */
+ /* can be done in SIMD, */
+ for (block_y = 4; block_y > 0; block_y--)
+ {
+ for (block_x = 4; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ itrans(dataBlock, pred, pred, 20);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ itrans(dataBlock, curL, curL, pitch);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ pred += 4;
+#else
+ curL += 4;
+#endif
+ }
+ dataBlock += 48;
+#ifdef USE_PRED_BLOCK
+ pred += 64;
+#else
+ curL += ((pitch << 2) - 16);
+#endif
+ }
+ }
+
+ offset = (offset >> 2) + (video->mb_x << 2); //((video->mb_y << 3)* pitch + (video->mb_x << 3));
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+
+#ifdef MB_BASED_DEBLOCK
+ video->pintra_pred_top_cb = video->intra_pred_top_cb + (video->mb_x << 3);
+ video->pintra_pred_left_cb = video->intra_pred_left_cb + 1;
+ video->intra_pred_topleft_cb = video->intra_pred_left_cb[0];
+ video->pintra_pred_top_cr = video->intra_pred_top_cr + (video->mb_x << 3);
+ video->pintra_pred_left_cr = video->intra_pred_left_cr + 1;
+ video->intra_pred_topleft_cr = video->intra_pred_left_cr[0];
+ pitch = 1;
+#else
+ pitch >>= 1;
+ video->pintra_pred_top_cb = curCb - pitch;
+ video->pintra_pred_left_cb = curCb - 1;
+ video->pintra_pred_top_cr = curCr - pitch;
+ video->pintra_pred_left_cr = curCr - 1;
+
+ if (video->mb_y)
+ {
+ video->intra_pred_topleft_cb = *(curCb - pitch - 1);
+ video->intra_pred_topleft_cr = *(curCr - pitch - 1);
+ }
+#endif
+
+#ifdef USE_PRED_BLOCK
+ predCb = video->pred + 452;
+ predCr = predCb + 144;
+ video->pred_pitch = 12;
+#else
+ predCb = curCb;
+ predCr = curCr;
+ video->pred_pitch = currPic->pitch >> 1;
+#endif
+ /* chrominance */
+ switch (currMB->intra_chroma_pred_mode)
+ {
+ case AVC_IC_DC: /* Intra_Chroma_DC */
+ Intra_Chroma_DC(video, pitch, predCb, predCr);
+ break;
+ case AVC_IC_Horizontal: /* Intra_Chroma_Horizontal */
+ if (video->intraAvailA)
+ {
+ /* check availability of left */
+ Intra_Chroma_Horizontal(video, pitch, predCb, predCr);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ case AVC_IC_Vertical: /* Intra_Chroma_Vertical */
+ if (video->intraAvailB)
+ {
+ /* check availability of top */
+ Intra_Chroma_Vertical(video, predCb, predCr);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ case AVC_IC_Plane: /* Intra_Chroma_Plane */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ /* check availability of top and left */
+ Intra_Chroma_Plane(video, pitch, predCb, predCr);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* transform, done in raster scan manner */
+ pitch = currPic->pitch >> 1;
+
+ for (block_y = 2; block_y > 0; block_y--)
+ {
+ for (block_x = 2; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, predCb, predCb, 12);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, curCb, curCb, pitch);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ predCb += 4;
+#else
+ curCb += 4;
+#endif
+ }
+ for (block_x = 2; block_x > 0; block_x--)
+ {
+#ifdef USE_PRED_BLOCK
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, predCr, predCr, 12);
+ }
+#else
+ if (cbp4x4&1)
+ {
+ ictrans(dataBlock, curCr, curCr, pitch);
+ }
+#endif
+ cbp4x4 >>= 1;
+ dataBlock += 4;
+#ifdef USE_PRED_BLOCK
+ predCr += 4;
+#else
+ curCr += 4;
+#endif
+ }
+ dataBlock += 48;
+#ifdef USE_PRED_BLOCK
+ predCb += 40;
+ predCr += 40;
+#else
+ curCb += ((pitch << 2) - 8);
+ curCr += ((pitch << 2) - 8);
+#endif
+ }
+
+#ifdef MB_BASED_DEBLOCK
+ SaveNeighborForIntraPred(video, offset);
+#endif
+ return AVC_SUCCESS;
+}
+
+#ifdef MB_BASED_DEBLOCK
+void SaveNeighborForIntraPred(AVCCommonObj *video, int offset)
+{
+ AVCPictureData *currPic = video->currPic;
+ int pitch;
+ uint8 *pred, *predCb, *predCr;
+ uint8 *tmp_ptr, tmp_byte;
+ uint32 tmp_word;
+ int mb_x = video->mb_x;
+
+ /* save the value for intra prediction */
+#ifdef USE_PRED_BLOCK
+ pitch = 20;
+ pred = video->pred + 384; /* bottom line for Y */
+ predCb = pred + 152; /* bottom line for Cb */
+ predCr = predCb + 144; /* bottom line for Cr */
+#else
+ pitch = currPic->pitch;
+ tmp_word = offset + (pitch << 2) - (pitch >> 1);
+ predCb = currPic->Scb + tmp_word;/* bottom line for Cb */
+ predCr = currPic->Scr + tmp_word;/* bottom line for Cr */
+
+ offset = (offset << 2) - (mb_x << 4);
+ pred = currPic->Sl + offset + (pitch << 4) - pitch;/* bottom line for Y */
+
+#endif
+
+ video->intra_pred_topleft = video->intra_pred_top[(mb_x<<4)+15];
+ video->intra_pred_topleft_cb = video->intra_pred_top_cb[(mb_x<<3)+7];
+ video->intra_pred_topleft_cr = video->intra_pred_top_cr[(mb_x<<3)+7];
+
+ /* then copy to video->intra_pred_top, intra_pred_top_cb, intra_pred_top_cr */
+ /*memcpy(video->intra_pred_top + (mb_x<<4), pred, 16);
+ memcpy(video->intra_pred_top_cb + (mb_x<<3), predCb, 8);
+ memcpy(video->intra_pred_top_cr + (mb_x<<3), predCr, 8);*/
+ tmp_ptr = video->intra_pred_top + (mb_x << 4);
+ *((uint32*)tmp_ptr) = *((uint32*)pred);
+ *((uint32*)(tmp_ptr + 4)) = *((uint32*)(pred + 4));
+ *((uint32*)(tmp_ptr + 8)) = *((uint32*)(pred + 8));
+ *((uint32*)(tmp_ptr + 12)) = *((uint32*)(pred + 12));
+ tmp_ptr = video->intra_pred_top_cb + (mb_x << 3);
+ *((uint32*)tmp_ptr) = *((uint32*)predCb);
+ *((uint32*)(tmp_ptr + 4)) = *((uint32*)(predCb + 4));
+ tmp_ptr = video->intra_pred_top_cr + (mb_x << 3);
+ *((uint32*)tmp_ptr) = *((uint32*)predCr);
+ *((uint32*)(tmp_ptr + 4)) = *((uint32*)(predCr + 4));
+
+
+ /* now save last column */
+#ifdef USE_PRED_BLOCK
+ pred = video->pred + 99; /* last column*/
+#else
+ pred -= ((pitch << 4) - pitch - 15); /* last column */
+#endif
+ tmp_ptr = video->intra_pred_left;
+ tmp_word = video->intra_pred_topleft;
+ tmp_byte = *(pred);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)tmp_ptr) = tmp_word;
+ tmp_word = *(pred += pitch);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)(tmp_ptr += 4)) = tmp_word;
+ tmp_word = *(pred += pitch);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)(tmp_ptr += 4)) = tmp_word;
+ tmp_word = *(pred += pitch);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(pred += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)(tmp_ptr += 4)) = tmp_word;
+ *(tmp_ptr += 4) = *(pred += pitch);
+
+ /* now for Cb */
+#ifdef USE_PRED_BLOCK
+ predCb = video->pred + 459;
+ pitch = 12;
+#else
+ pitch >>= 1;
+ predCb -= (7 * pitch - 7);
+#endif
+ tmp_ptr = video->intra_pred_left_cb;
+ tmp_word = video->intra_pred_topleft_cb;
+ tmp_byte = *(predCb);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(predCb += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(predCb += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)tmp_ptr) = tmp_word;
+ tmp_word = *(predCb += pitch);
+ tmp_byte = *(predCb += pitch);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(predCb += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(predCb += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)(tmp_ptr += 4)) = tmp_word;
+ *(tmp_ptr += 4) = *(predCb += pitch);
+
+ /* now for Cr */
+#ifdef USE_PRED_BLOCK
+ predCr = video->pred + 603;
+#else
+ predCr -= (7 * pitch - 7);
+#endif
+ tmp_ptr = video->intra_pred_left_cr;
+ tmp_word = video->intra_pred_topleft_cr;
+ tmp_byte = *(predCr);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(predCr += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(predCr += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)tmp_ptr) = tmp_word;
+ tmp_word = *(predCr += pitch);
+ tmp_byte = *(predCr += pitch);
+ tmp_word |= (tmp_byte << 8);
+ tmp_byte = *(predCr += pitch);
+ tmp_word |= (tmp_byte << 16);
+ tmp_byte = *(predCr += pitch);
+ tmp_word |= (tmp_byte << 24);
+ *((uint32*)(tmp_ptr += 4)) = tmp_word;
+ *(tmp_ptr += 4) = *(predCr += pitch);
+
+ return ;
+}
+#endif /* MB_BASED_DEBLOCK */
+
+AVCStatus Intra_4x4(AVCCommonObj *video, int block_x, int block_y, uint8 *comp)
+{
+ AVCMacroblock *currMB = video->currMB;
+ int block_offset;
+ AVCNeighborAvailability availability;
+ int pitch = video->currPic->pitch;
+
+#ifdef USE_PRED_BLOCK
+ block_offset = (block_y * 80) + (block_x << 2);
+#else
+ block_offset = (block_y << 2) * pitch + (block_x << 2);
+#endif
+
+#ifdef MB_BASED_DEBLOCK
+ /* boundary blocks use video->pred_intra_top, pred_intra_left, pred_intra_topleft */
+ if (!block_x)
+ {
+ video->pintra_pred_left = video->intra_pred_left + 1 + (block_y << 2);
+ pitch = 1;
+ }
+ else
+ {
+ video->pintra_pred_left = video->pred_block + block_offset - 1;
+ pitch = video->pred_pitch;
+ }
+
+ if (!block_y)
+ {
+ video->pintra_pred_top = video->intra_pred_top + (block_x << 2) + (video->mb_x << 4);
+ }
+ else
+ {
+ video->pintra_pred_top = video->pred_block + block_offset - video->pred_pitch;
+ }
+
+ if (!block_x)
+ {
+ video->intra_pred_topleft = video->intra_pred_left[block_y<<2];
+ }
+ else if (!block_y)
+ {
+ video->intra_pred_topleft = video->intra_pred_top[(video->mb_x<<4)+(block_x<<2)-1];
+ }
+ else
+ {
+ video->intra_pred_topleft = video->pred_block[block_offset - video->pred_pitch - 1];
+ }
+
+#else
+ /* normal case */
+ video->pintra_pred_top = comp - pitch;
+ video->pintra_pred_left = comp - 1;
+ if (video->mb_y || block_y)
+ {
+ video->intra_pred_topleft = *(comp - pitch - 1);
+ }
+#endif
+
+ switch (currMB->i4Mode[(block_y << 2) + block_x])
+ {
+ case AVC_I4_Vertical: /* Intra_4x4_Vertical */
+ if (block_y > 0 || video->intraAvailB)/* to prevent out-of-bound access*/
+ {
+ Intra_4x4_Vertical(video, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+ case AVC_I4_Horizontal: /* Intra_4x4_Horizontal */
+ if (block_x || video->intraAvailA) /* to prevent out-of-bound access */
+ {
+ Intra_4x4_Horizontal(video, pitch, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+ case AVC_I4_DC: /* Intra_4x4_DC */
+ availability.left = TRUE;
+ availability.top = TRUE;
+ if (!block_y)
+ { /* check availability up */
+ availability.top = video->intraAvailB ;
+ }
+ if (!block_x)
+ { /* check availability left */
+ availability.left = video->intraAvailA ;
+ }
+ Intra_4x4_DC(video, pitch, block_offset, &availability);
+ break;
+
+ case AVC_I4_Diagonal_Down_Left: /* Intra_4x4_Diagonal_Down_Left */
+ /* lookup table will be more appropriate for this case */
+ if (block_y == 0 && !video->intraAvailB)
+ {
+ return AVC_FAIL;
+ }
+
+ availability.top_right = BlkTopRight[(block_y<<2) + block_x];
+
+ if (availability.top_right == 2)
+ {
+ availability.top_right = video->intraAvailB;
+ }
+ else if (availability.top_right == 3)
+ {
+ availability.top_right = video->intraAvailC;
+ }
+
+ Intra_4x4_Down_Left(video, block_offset, &availability);
+ break;
+
+ case AVC_I4_Diagonal_Down_Right: /* Intra_4x4_Diagonal_Down_Right */
+ if ((block_y && block_x) /* to prevent out-of-bound access */
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
+ {
+ Intra_4x4_Diagonal_Down_Right(video, pitch, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+ case AVC_I4_Vertical_Right: /* Intra_4x4_Vertical_Right */
+ if ((block_y && block_x) /* to prevent out-of-bound access */
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
+ {
+ Intra_4x4_Diagonal_Vertical_Right(video, pitch, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+ case AVC_I4_Horizontal_Down: /* Intra_4x4_Horizontal_Down */
+ if ((block_y && block_x) /* to prevent out-of-bound access */
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
+ {
+ Intra_4x4_Diagonal_Horizontal_Down(video, pitch, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+ case AVC_I4_Vertical_Left: /* Intra_4x4_Vertical_Left */
+ /* lookup table may be more appropriate for this case */
+ if (block_y == 0 && !video->intraAvailB)
+ {
+ return AVC_FAIL;
+ }
+
+ availability.top_right = BlkTopRight[(block_y<<2) + block_x];
+
+ if (availability.top_right == 2)
+ {
+ availability.top_right = video->intraAvailB;
+ }
+ else if (availability.top_right == 3)
+ {
+ availability.top_right = video->intraAvailC;
+ }
+
+ Intra_4x4_Vertical_Left(video, block_offset, &availability);
+ break;
+
+ case AVC_I4_Horizontal_Up: /* Intra_4x4_Horizontal_Up */
+ if (block_x || video->intraAvailA)
+ {
+ Intra_4x4_Horizontal_Up(video, pitch, block_offset);
+ }
+ else
+ {
+ return AVC_FAIL;
+ }
+ break;
+
+
+ default:
+
+ break;
+ }
+
+ return AVC_SUCCESS;
+}
+
+
+/* =============================== BEGIN 4x4
+MODES======================================*/
+void Intra_4x4_Vertical(AVCCommonObj *video, int block_offset)
+{
+ uint8 *comp_ref = video->pintra_pred_top;
+ uint32 temp;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ /*P = (int) *comp_ref++;
+ Q = (int) *comp_ref++;
+ R = (int) *comp_ref++;
+ S = (int) *comp_ref++;
+ temp = S|(R<<8)|(Q<<16)|(P<<24);*/
+ temp = *((uint32*)comp_ref);
+
+ *((uint32*)pred) = temp; /* write 4 at a time */
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Horizontal(AVCCommonObj *video, int pitch, int block_offset)
+{
+ uint8 *comp_ref = video->pintra_pred_left;
+ uint32 temp;
+ int P;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ P = *comp_ref;
+ temp = P | (P << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ comp_ref += pitch;
+ P = *comp_ref;
+ temp = P | (P << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ comp_ref += pitch;
+ P = *comp_ref;
+ temp = P | (P << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ comp_ref += pitch;
+ P = *comp_ref;
+ temp = P | (P << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_DC(AVCCommonObj *video, int pitch, int block_offset,
+ AVCNeighborAvailability *availability)
+{
+ uint8 *comp_ref = video->pintra_pred_left;
+ uint32 temp;
+ int DC;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ if (availability->left)
+ {
+ DC = *comp_ref;
+ comp_ref += pitch;
+ DC += *comp_ref;
+ comp_ref += pitch;
+ DC += *comp_ref;
+ comp_ref += pitch;
+ DC += *comp_ref;
+ comp_ref = video->pintra_pred_top;
+
+ if (availability->top)
+ {
+ DC = (comp_ref[0] + comp_ref[1] + comp_ref[2] + comp_ref[3] + DC + 4) >> 3;
+ }
+ else
+ {
+ DC = (DC + 2) >> 2;
+
+ }
+ }
+ else if (availability->top)
+ {
+ comp_ref = video->pintra_pred_top;
+ DC = (comp_ref[0] + comp_ref[1] + comp_ref[2] + comp_ref[3] + 2) >> 2;
+
+ }
+ else
+ {
+ DC = 128;
+ }
+
+ temp = DC | (DC << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Down_Left(AVCCommonObj *video, int block_offset,
+ AVCNeighborAvailability *availability)
+{
+ uint8 *comp_refx = video->pintra_pred_top;
+ uint32 temp;
+ int r0, r1, r2, r3, r4, r5, r6, r7;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ r0 = *comp_refx++;
+ r1 = *comp_refx++;
+ r2 = *comp_refx++;
+ r3 = *comp_refx++;
+ if (availability->top_right)
+ {
+ r4 = *comp_refx++;
+ r5 = *comp_refx++;
+ r6 = *comp_refx++;
+ r7 = *comp_refx++;
+ }
+ else
+ {
+ r4 = r3;
+ r5 = r3;
+ r6 = r3;
+ r7 = r3;
+ }
+
+ r0 += (r1 << 1);
+ r0 += r2;
+ r0 += 2;
+ r0 >>= 2;
+ r1 += (r2 << 1);
+ r1 += r3;
+ r1 += 2;
+ r1 >>= 2;
+ r2 += (r3 << 1);
+ r2 += r4;
+ r2 += 2;
+ r2 >>= 2;
+ r3 += (r4 << 1);
+ r3 += r5;
+ r3 += 2;
+ r3 >>= 2;
+ r4 += (r5 << 1);
+ r4 += r6;
+ r4 += 2;
+ r4 >>= 2;
+ r5 += (r6 << 1);
+ r5 += r7;
+ r5 += 2;
+ r5 >>= 2;
+ r6 += (3 * r7);
+ r6 += 2;
+ r6 >>= 2;
+
+ temp = r0 | (r1 << 8);
+ temp |= (r2 << 16);
+ temp |= (r3 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = (temp >> 8) | (r4 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = (temp >> 8) | (r5 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = (temp >> 8) | (r6 << 24);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Diagonal_Down_Right(AVCCommonObj *video, int pitch, int
+ block_offset)
+{
+ uint8 *comp_refx = video->pintra_pred_top;
+ uint8 *comp_refy = video->pintra_pred_left;
+ uint32 temp;
+ int P_x, Q_x, R_x, P_y, Q_y, R_y, D;
+ int x0, x1, x2;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ temp = *((uint32*)comp_refx); /* read 4 bytes */
+ x0 = temp & 0xFF;
+ x1 = (temp >> 8) & 0xFF;
+ x2 = (temp >> 16) & 0xFF;
+
+ Q_x = (x0 + 2 * x1 + x2 + 2) >> 2;
+ R_x = (x1 + 2 * x2 + (temp >> 24) + 2) >> 2;
+
+ x2 = video->intra_pred_topleft; /* re-use x2 instead of y0 */
+ P_x = (x2 + 2 * x0 + x1 + 2) >> 2;
+
+ x1 = *comp_refy;
+ comp_refy += pitch; /* re-use x1 instead of y1 */
+ D = (x0 + 2 * x2 + x1 + 2) >> 2;
+
+ x0 = *comp_refy;
+ comp_refy += pitch; /* re-use x0 instead of y2 */
+ P_y = (x2 + 2 * x1 + x0 + 2) >> 2;
+
+ x2 = *comp_refy;
+ comp_refy += pitch; /* re-use x2 instead of y3 */
+ Q_y = (x1 + 2 * x0 + x2 + 2) >> 2;
+
+ x1 = *comp_refy; /* re-use x1 instead of y4 */
+ R_y = (x0 + 2 * x2 + x1 + 2) >> 2;
+
+ /* we can pack these */
+ temp = D | (P_x << 8); //[D P_x Q_x R_x]
+ //[P_y D P_x Q_x]
+ temp |= (Q_x << 16); //[Q_y P_y D P_x]
+ temp |= (R_x << 24); //[R_y Q_y P_y D ]
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = P_y | (D << 8);
+ temp |= (P_x << 16);
+ temp |= (Q_x << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = Q_y | (P_y << 8);
+ temp |= (D << 16);
+ temp |= (P_x << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = R_y | (Q_y << 8);
+ temp |= (P_y << 16);
+ temp |= (D << 24);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Diagonal_Vertical_Right(AVCCommonObj *video, int pitch, int block_offset)
+{
+ uint8 *comp_refx = video->pintra_pred_top;
+ uint8 *comp_refy = video->pintra_pred_left;
+ uint32 temp;
+ int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2, D;
+ int x0, x1, x2;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ x0 = *comp_refx++;
+ x1 = *comp_refx++;
+ Q0 = x0 + x1 + 1;
+
+ x2 = *comp_refx++;
+ R0 = x1 + x2 + 1;
+
+ x1 = *comp_refx++; /* reuse x1 instead of x3 */
+ S0 = x2 + x1 + 1;
+
+ x1 = video->intra_pred_topleft; /* reuse x1 instead of y0 */
+ P0 = x1 + x0 + 1;
+
+ x2 = *comp_refy;
+ comp_refy += pitch; /* reuse x2 instead of y1 */
+ D = (x2 + 2 * x1 + x0 + 2) >> 2;
+
+ P1 = (P0 + Q0) >> 2;
+ Q1 = (Q0 + R0) >> 2;
+ R1 = (R0 + S0) >> 2;
+
+ P0 >>= 1;
+ Q0 >>= 1;
+ R0 >>= 1;
+ S0 >>= 1;
+
+ x0 = *comp_refy;
+ comp_refy += pitch; /* reuse x0 instead of y2 */
+ P2 = (x1 + 2 * x2 + x0 + 2) >> 2;
+ x1 = *comp_refy;
+ comp_refy += pitch; /* reuse x1 instead of y3 */
+ Q2 = (x2 + 2 * x0 + x1 + 2) >> 2;
+
+ temp = P0 | (Q0 << 8); //[P0 Q0 R0 S0]
+ //[D P1 Q1 R1]
+ temp |= (R0 << 16); //[P2 P0 Q0 R0]
+ temp |= (S0 << 24); //[Q2 D P1 Q1]
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = D | (P1 << 8);
+ temp |= (Q1 << 16);
+ temp |= (R1 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = P2 | (P0 << 8);
+ temp |= (Q0 << 16);
+ temp |= (R0 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = Q2 | (D << 8);
+ temp |= (P1 << 16);
+ temp |= (Q1 << 24);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Diagonal_Horizontal_Down(AVCCommonObj *video, int pitch,
+ int block_offset)
+{
+ uint8 *comp_refx = video->pintra_pred_top;
+ uint8 *comp_refy = video->pintra_pred_left;
+ uint32 temp;
+ int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2, D;
+ int x0, x1, x2;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ x0 = *comp_refx++;
+ x1 = *comp_refx++;
+ x2 = *comp_refx++;
+ Q2 = (x0 + 2 * x1 + x2 + 2) >> 2;
+
+ x2 = video->intra_pred_topleft; /* reuse x2 instead of y0 */
+ P2 = (x2 + 2 * x0 + x1 + 2) >> 2;
+
+ x1 = *comp_refy;
+ comp_refy += pitch; /* reuse x1 instead of y1 */
+ D = (x1 + 2 * x2 + x0 + 2) >> 2;
+ P0 = x2 + x1 + 1;
+
+ x0 = *comp_refy;
+ comp_refy += pitch; /* reuse x0 instead of y2 */
+ Q0 = x1 + x0 + 1;
+
+ x1 = *comp_refy;
+ comp_refy += pitch; /* reuse x1 instead of y3 */
+ R0 = x0 + x1 + 1;
+
+ x2 = *comp_refy; /* reuse x2 instead of y4 */
+ S0 = x1 + x2 + 1;
+
+ P1 = (P0 + Q0) >> 2;
+ Q1 = (Q0 + R0) >> 2;
+ R1 = (R0 + S0) >> 2;
+
+ P0 >>= 1;
+ Q0 >>= 1;
+ R0 >>= 1;
+ S0 >>= 1;
+
+
+ /* we can pack these */
+ temp = P0 | (D << 8); //[P0 D P2 Q2]
+ //[Q0 P1 P0 D ]
+ temp |= (P2 << 16); //[R0 Q1 Q0 P1]
+ temp |= (Q2 << 24); //[S0 R1 R0 Q1]
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = Q0 | (P1 << 8);
+ temp |= (P0 << 16);
+ temp |= (D << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = R0 | (Q1 << 8);
+ temp |= (Q0 << 16);
+ temp |= (P1 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = S0 | (R1 << 8);
+ temp |= (R0 << 16);
+ temp |= (Q1 << 24);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+
+void Intra_4x4_Vertical_Left(AVCCommonObj *video, int block_offset, AVCNeighborAvailability *availability)
+{
+ uint8 *comp_refx = video->pintra_pred_top;
+ uint32 temp1, temp2;
+ int x0, x1, x2, x3, x4, x5, x6;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ x0 = *comp_refx++;
+ x1 = *comp_refx++;
+ x2 = *comp_refx++;
+ x3 = *comp_refx++;
+ if (availability->top_right)
+ {
+ x4 = *comp_refx++;
+ x5 = *comp_refx++;
+ x6 = *comp_refx++;
+ }
+ else
+ {
+ x4 = x3;
+ x5 = x3;
+ x6 = x3;
+ }
+
+ x0 += x1 + 1;
+ x1 += x2 + 1;
+ x2 += x3 + 1;
+ x3 += x4 + 1;
+ x4 += x5 + 1;
+ x5 += x6 + 1;
+
+ temp1 = (x0 >> 1);
+ temp1 |= ((x1 >> 1) << 8);
+ temp1 |= ((x2 >> 1) << 16);
+ temp1 |= ((x3 >> 1) << 24);
+
+ *((uint32*)pred) = temp1;
+ pred += pred_pitch;
+
+ temp2 = ((x0 + x1) >> 2);
+ temp2 |= (((x1 + x2) >> 2) << 8);
+ temp2 |= (((x2 + x3) >> 2) << 16);
+ temp2 |= (((x3 + x4) >> 2) << 24);
+
+ *((uint32*)pred) = temp2;
+ pred += pred_pitch;
+
+ temp1 = (temp1 >> 8) | ((x4 >> 1) << 24); /* rotate out old value */
+ *((uint32*)pred) = temp1;
+ pred += pred_pitch;
+
+ temp2 = (temp2 >> 8) | (((x4 + x5) >> 2) << 24); /* rotate out old value */
+ *((uint32*)pred) = temp2;
+ pred += pred_pitch;
+
+ return ;
+}
+
+void Intra_4x4_Horizontal_Up(AVCCommonObj *video, int pitch, int block_offset)
+{
+ uint8 *comp_refy = video->pintra_pred_left;
+ uint32 temp;
+ int Q0, R0, Q1, D0, D1, P0, P1;
+ int y0, y1, y2, y3;
+ uint8 *pred = video->pred_block + block_offset;
+ int pred_pitch = video->pred_pitch;
+
+ y0 = *comp_refy;
+ comp_refy += pitch;
+ y1 = *comp_refy;
+ comp_refy += pitch;
+ y2 = *comp_refy;
+ comp_refy += pitch;
+ y3 = *comp_refy;
+
+ Q0 = (y1 + y2 + 1) >> 1;
+ Q1 = (y1 + (y2 << 1) + y3 + 2) >> 2;
+ P0 = ((y0 + y1 + 1) >> 1);
+ P1 = ((y0 + (y1 << 1) + y2 + 2) >> 2);
+
+ temp = P0 | (P1 << 8); // [P0 P1 Q0 Q1]
+ temp |= (Q0 << 16); // [Q0 Q1 R0 DO]
+ temp |= (Q1 << 24); // [R0 D0 D1 D1]
+ *((uint32*)pred) = temp; // [D1 D1 D1 D1]
+ pred += pred_pitch;
+
+ D0 = (y2 + 3 * y3 + 2) >> 2;
+ R0 = (y2 + y3 + 1) >> 1;
+
+ temp = Q0 | (Q1 << 8);
+ temp |= (R0 << 16);
+ temp |= (D0 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ D1 = y3;
+
+ temp = R0 | (D0 << 8);
+ temp |= (D1 << 16);
+ temp |= (D1 << 24);
+ *((uint32*)pred) = temp;
+ pred += pred_pitch;
+
+ temp = D1 | (D1 << 8);
+ temp |= (temp << 16);
+ *((uint32*)pred) = temp;
+
+ return ;
+}
+/* =============================== END 4x4 MODES======================================*/
+void Intra_16x16_Vertical(AVCCommonObj *video)
+{
+ int i;
+ uint32 temp1, temp2, temp3, temp4;
+ uint8 *comp_ref = video->pintra_pred_top;
+ uint8 *pred = video->pred_block;
+ int pred_pitch = video->pred_pitch;
+
+ temp1 = *((uint32*)comp_ref);
+ comp_ref += 4;
+
+ temp2 = *((uint32*)comp_ref);
+ comp_ref += 4;
+
+ temp3 = *((uint32*)comp_ref);
+ comp_ref += 4;
+
+ temp4 = *((uint32*)comp_ref);
+ comp_ref += 4;
+
+ i = 16;
+ while (i > 0)
+ {
+ *((uint32*)pred) = temp1;
+ *((uint32*)(pred + 4)) = temp2;
+ *((uint32*)(pred + 8)) = temp3;
+ *((uint32*)(pred + 12)) = temp4;
+ pred += pred_pitch;
+ i--;
+ }
+
+ return ;
+}
+
+void Intra_16x16_Horizontal(AVCCommonObj *video, int pitch)
+{
+ int i;
+ uint32 temp;
+ uint8 *comp_ref = video->pintra_pred_left;
+ uint8 *pred = video->pred_block;
+ int pred_pitch = video->pred_pitch;
+
+ for (i = 0; i < 16; i++)
+ {
+ temp = *comp_ref;
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((uint32*)pred) = temp;
+ *((uint32*)(pred + 4)) = temp;
+ *((uint32*)(pred + 8)) = temp;
+ *((uint32*)(pred + 12)) = temp;
+ pred += pred_pitch;
+ comp_ref += pitch;
+ }
+}
+
+
+void Intra_16x16_DC(AVCCommonObj *video, int pitch)
+{
+ int i;
+ uint32 temp, temp2;
+ uint8 *comp_ref_x = video->pintra_pred_top;
+ uint8 *comp_ref_y = video->pintra_pred_left;
+ int sum = 0;
+ uint8 *pred = video->pred_block;
+ int pred_pitch = video->pred_pitch;
+
+ if (video->intraAvailB)
+ {
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ sum = temp + (temp >> 16);
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ sum += temp + (temp >> 16);
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ sum += temp + (temp >> 16);
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ sum += temp + (temp >> 16);
+ sum &= 0xFFFF;
+
+ if (video->intraAvailA)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ sum += (*comp_ref_y);
+ comp_ref_y += pitch;
+ }
+ sum = (sum + 16) >> 5;
+ }
+ else
+ {
+ sum = (sum + 8) >> 4;
+ }
+ }
+ else if (video->intraAvailA)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ sum += *comp_ref_y;
+ comp_ref_y += pitch;
+ }
+ sum = (sum + 8) >> 4;
+ }
+ else
+ {
+ sum = 128;
+ }
+
+ temp = sum | (sum << 8);
+ temp |= (temp << 16);
+
+ for (i = 0; i < 16; i++)
+ {
+ *((uint32*)pred) = temp;
+ *((uint32*)(pred + 4)) = temp;
+ *((uint32*)(pred + 8)) = temp;
+ *((uint32*)(pred + 12)) = temp;
+ pred += pred_pitch;
+ }
+
+}
+
+void Intra_16x16_Plane(AVCCommonObj *video, int pitch)
+{
+ int i, a_16, b, c, factor_c;
+ uint8 *comp_ref_x = video->pintra_pred_top;
+ uint8 *comp_ref_y = video->pintra_pred_left;
+ uint8 *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
+ int H = 0, V = 0 , tmp;
+ uint8 *pred = video->pred_block;
+ uint32 temp;
+ uint8 byte1, byte2, byte3;
+ int value;
+ int pred_pitch = video->pred_pitch;
+
+ comp_ref_x0 = comp_ref_x + 8;
+ comp_ref_x1 = comp_ref_x + 6;
+ comp_ref_y0 = comp_ref_y + (pitch << 3);
+ comp_ref_y1 = comp_ref_y + 6 * pitch;
+
+ for (i = 1; i < 8; i++)
+ {
+ H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+ comp_ref_y0 += pitch;
+ comp_ref_y1 -= pitch;
+ }
+
+ H += i * (*comp_ref_x0++ - video->intra_pred_topleft);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+
+ a_16 = ((*(comp_ref_x + 15) + *(comp_ref_y + 15 * pitch)) << 4) + 16;;
+ b = (5 * H + 32) >> 6;
+ c = (5 * V + 32) >> 6;
+
+ tmp = 0;
+
+ for (i = 0; i < 16; i++)
+ {
+ factor_c = a_16 + c * (tmp++ - 7);
+
+ factor_c -= 7 * b;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)pred) = temp;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)(pred + 4)) = temp;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)(pred + 8)) = temp;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)(pred + 12)) = temp;
+ pred += pred_pitch;
+ }
+}
+
+/************** Chroma intra prediction *********************/
+
+void Intra_Chroma_DC(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
+{
+ int i;
+ uint32 temp, temp2, pred_a, pred_b;
+ uint8 *comp_ref_x, *comp_ref_y;
+ uint8 *comp_ref_cb_x = video->pintra_pred_top_cb;
+ uint8 *comp_ref_cb_y = video->pintra_pred_left_cb;
+ uint8 *comp_ref_cr_x = video->pintra_pred_top_cr;
+ uint8 *comp_ref_cr_y = video->pintra_pred_left_cr;
+ int component, j;
+ int sum_x0, sum_x1, sum_y0, sum_y1;
+ int pred_0[2], pred_1[2], pred_2[2], pred_3[2];
+ int pred_pitch = video->pred_pitch;
+ uint8 *pred;
+
+ if (video->intraAvailB & video->intraAvailA)
+ {
+ comp_ref_x = comp_ref_cb_x;
+ comp_ref_y = comp_ref_cb_y;
+ for (i = 0; i < 2; i++)
+ {
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ temp += (temp >> 16);
+ sum_x0 = temp & 0xFFFF;
+
+ temp = *((uint32*)comp_ref_x);
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ temp += (temp >> 16);
+ sum_x1 = temp & 0xFFFF;
+
+ pred_1[i] = (sum_x1 + 2) >> 2;
+
+ sum_y0 = *comp_ref_y;
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+
+ sum_y1 = *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+
+ pred_2[i] = (sum_y1 + 2) >> 2;
+
+ pred_0[i] = (sum_y0 + sum_x0 + 4) >> 3;
+ pred_3[i] = (sum_y1 + sum_x1 + 4) >> 3;
+
+ comp_ref_x = comp_ref_cr_x;
+ comp_ref_y = comp_ref_cr_y;
+ }
+ }
+
+ else if (video->intraAvailA)
+ {
+ comp_ref_y = comp_ref_cb_y;
+ for (i = 0; i < 2; i++)
+ {
+ sum_y0 = *comp_ref_y;
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+
+ sum_y1 = *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+
+ pred_0[i] = pred_1[i] = (sum_y0 + 2) >> 2;
+ pred_2[i] = pred_3[i] = (sum_y1 + 2) >> 2;
+ comp_ref_y = comp_ref_cr_y;
+ }
+ }
+ else if (video->intraAvailB)
+ {
+ comp_ref_x = comp_ref_cb_x;
+ for (i = 0; i < 2; i++)
+ {
+ temp = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ temp += (temp >> 16);
+ sum_x0 = temp & 0xFFFF;
+
+ temp = *((uint32*)comp_ref_x);
+ temp2 = (temp >> 8) & 0xFF00FF;
+ temp &= 0xFF00FF;
+ temp += temp2;
+ temp += (temp >> 16);
+ sum_x1 = temp & 0xFFFF;
+
+ pred_0[i] = pred_2[i] = (sum_x0 + 2) >> 2;
+ pred_1[i] = pred_3[i] = (sum_x1 + 2) >> 2;
+ comp_ref_x = comp_ref_cr_x;
+ }
+ }
+ else
+ {
+ pred_0[0] = pred_0[1] = pred_1[0] = pred_1[1] =
+ pred_2[0] = pred_2[1] = pred_3[0] = pred_3[1] = 128;
+ }
+
+ pred = predCb;
+ for (component = 0; component < 2; component++)
+ {
+ pred_a = pred_0[component];
+ pred_b = pred_1[component];
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ pred_b |= (pred_b << 8);
+ pred_b |= (pred_b << 16);
+
+ for (i = 4; i < 6; i++)
+ {
+ for (j = 0; j < 4; j++) /* 4 lines */
+ {
+ *((uint32*)pred) = pred_a;
+ *((uint32*)(pred + 4)) = pred_b;
+ pred += pred_pitch; /* move to the next line */
+ }
+ pred_a = pred_2[component];
+ pred_b = pred_3[component];
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ pred_b |= (pred_b << 8);
+ pred_b |= (pred_b << 16);
+ }
+ pred = predCr; /* point to cr */
+ }
+}
+
+void Intra_Chroma_Horizontal(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
+{
+ int i;
+ uint32 temp;
+ uint8 *comp_ref_cb_y = video->pintra_pred_left_cb;
+ uint8 *comp_ref_cr_y = video->pintra_pred_left_cr;
+ uint8 *comp;
+ int component, j;
+ int pred_pitch = video->pred_pitch;
+ uint8 *pred;
+
+ comp = comp_ref_cb_y;
+ pred = predCb;
+ for (component = 0; component < 2; component++)
+ {
+ for (i = 4; i < 6; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ temp = *comp;
+ comp += pitch;
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((uint32*)pred) = temp;
+ *((uint32*)(pred + 4)) = temp;
+ pred += pred_pitch;
+ }
+ }
+ comp = comp_ref_cr_y;
+ pred = predCr; /* point to cr */
+ }
+
+}
+
+void Intra_Chroma_Vertical(AVCCommonObj *video, uint8 *predCb, uint8 *predCr)
+{
+ uint32 temp1, temp2;
+ uint8 *comp_ref_cb_x = video->pintra_pred_top_cb;
+ uint8 *comp_ref_cr_x = video->pintra_pred_top_cr;
+ uint8 *comp_ref;
+ int component, j;
+ int pred_pitch = video->pred_pitch;
+ uint8 *pred;
+
+ comp_ref = comp_ref_cb_x;
+ pred = predCb;
+ for (component = 0; component < 2; component++)
+ {
+ temp1 = *((uint32*)comp_ref);
+ temp2 = *((uint32*)(comp_ref + 4));
+ for (j = 0; j < 8; j++)
+ {
+ *((uint32*)pred) = temp1;
+ *((uint32*)(pred + 4)) = temp2;
+ pred += pred_pitch;
+ }
+ comp_ref = comp_ref_cr_x;
+ pred = predCr; /* point to cr */
+ }
+
+}
+
+void Intra_Chroma_Plane(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
+{
+ int i;
+ int a_16_C[2], b_C[2], c_C[2], a_16, b, c, factor_c;
+ uint8 *comp_ref_x, *comp_ref_y, *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
+ int component, j;
+ int H, V, tmp;
+ uint32 temp;
+ uint8 byte1, byte2, byte3;
+ int value;
+ uint8 topleft;
+ int pred_pitch = video->pred_pitch;
+ uint8 *pred;
+
+ comp_ref_x = video->pintra_pred_top_cb;
+ comp_ref_y = video->pintra_pred_left_cb;
+ topleft = video->intra_pred_topleft_cb;
+
+ for (component = 0; component < 2; component++)
+ {
+ H = V = 0;
+ comp_ref_x0 = comp_ref_x + 4;
+ comp_ref_x1 = comp_ref_x + 2;
+ comp_ref_y0 = comp_ref_y + (pitch << 2);
+ comp_ref_y1 = comp_ref_y + (pitch << 1);
+ for (i = 1; i < 4; i++)
+ {
+ H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+ comp_ref_y0 += pitch;
+ comp_ref_y1 -= pitch;
+ }
+ H += i * (*comp_ref_x0++ - topleft);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+ a_16_C[component] = ((*(comp_ref_x + 7) + *(comp_ref_y + 7 * pitch)) << 4) + 16;
+ b_C[component] = (17 * H + 16) >> 5;
+ c_C[component] = (17 * V + 16) >> 5;
+
+ comp_ref_x = video->pintra_pred_top_cr;
+ comp_ref_y = video->pintra_pred_left_cr;
+ topleft = video->intra_pred_topleft_cr;
+ }
+
+ pred = predCb;
+ for (component = 0; component < 2; component++)
+ {
+ a_16 = a_16_C[component];
+ b = b_C[component];
+ c = c_C[component];
+ tmp = 0;
+ for (i = 4; i < 6; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ factor_c = a_16 + c * (tmp++ - 3);
+
+ factor_c -= 3 * b;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)pred) = temp;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte2 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ byte3 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ temp = byte1 | (byte2 << 8);
+ temp |= (byte3 << 16);
+ temp |= (value << 24);
+ *((uint32*)(pred + 4)) = temp;
+ pred += pred_pitch;
+ }
+ }
+ pred = predCr; /* point to cr */
+ }
+}
+
diff --git a/media/libstagefright/codecs/avc/dec/src/residual.cpp b/media/libstagefright/codecs/avc/dec/src/residual.cpp
new file mode 100644
index 0000000..c68550d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/residual.cpp
@@ -0,0 +1,523 @@
+/* ------------------------------------------------------------------
+ * 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 <string.h>
+
+#include "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+
+AVCDec_Status DecodeIntraPCM(AVCCommonObj *video, AVCDecBitstream *stream)
+{
+ AVCDec_Status status;
+ int j;
+ int mb_x, mb_y, offset1;
+ uint8 *pDst;
+ uint32 byte0, byte1;
+ int pitch;
+
+ mb_x = video->mb_x;
+ mb_y = video->mb_y;
+
+#ifdef USE_PRED_BLOCK
+ pDst = video->pred_block + 84;
+ pitch = 20;
+#else
+ offset1 = (mb_x << 4) + (mb_y << 4) * video->PicWidthInSamplesL;
+ pDst = video->currPic->Sl + offset1;
+ pitch = video->currPic->pitch;
+#endif
+
+ /* at this point bitstream is byte-aligned */
+ j = 16;
+ while (j > 0)
+ {
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)pDst) = byte0;
+
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)(pDst + 4)) = byte0;
+
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)(pDst + 8)) = byte0;
+
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)(pDst + 12)) = byte0;
+ j--;
+ pDst += pitch;
+
+ if (status != AVCDEC_SUCCESS) /* check only once per line */
+ return status;
+ }
+
+#ifdef USE_PRED_BLOCK
+ pDst = video->pred_block + 452;
+ pitch = 12;
+#else
+ offset1 = (offset1 >> 2) + (mb_x << 2);
+ pDst = video->currPic->Scb + offset1;
+ pitch >>= 1;
+#endif
+
+ j = 8;
+ while (j > 0)
+ {
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)pDst) = byte0;
+
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)(pDst + 4)) = byte0;
+
+ j--;
+ pDst += pitch;
+
+ if (status != AVCDEC_SUCCESS) /* check only once per line */
+ return status;
+ }
+
+#ifdef USE_PRED_BLOCK
+ pDst = video->pred_block + 596;
+ pitch = 12;
+#else
+ pDst = video->currPic->Scr + offset1;
+#endif
+ j = 8;
+ while (j > 0)
+ {
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)pDst) = byte0;
+
+ status = BitstreamReadBits(stream, 8, (uint*) & byte0);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 8);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 16);
+ status = BitstreamReadBits(stream, 8, (uint*) & byte1);
+ byte0 |= (byte1 << 24);
+ *((uint32*)(pDst + 4)) = byte0;
+
+ j--;
+ pDst += pitch;
+
+ if (status != AVCDEC_SUCCESS) /* check only once per line */
+ return status;
+ }
+
+#ifdef MB_BASED_DEBLOCK
+ SaveNeighborForIntraPred(video, offset1);
+#endif
+
+ return AVCDEC_SUCCESS;
+}
+
+
+
+/* see subclause 7.3.5.3 and readCBPandCoeffsFromNAL() in JM*/
+AVCDec_Status residual(AVCDecObject *decvid, AVCMacroblock *currMB)
+{
+ AVCCommonObj *video = decvid->common;
+ int16 *block;
+ int level[16], run[16], numcoeff; /* output from residual_block_cavlc */
+ int block_x, i, j, k, idx, iCbCr;
+ int mbPartIdx, subMbPartIdx, mbPartIdx_X, mbPartIdx_Y;
+ int nC, maxNumCoeff = 16;
+ int coeffNum, start_scan = 0;
+ uint8 *zz_scan;
+ int Rq, Qq;
+ uint32 cbp4x4 = 0;
+
+ /* in 8.5.4, it only says if it's field macroblock. */
+
+ zz_scan = (uint8*) ZZ_SCAN_BLOCK;
+
+
+ /* see 8.5.8 for the initialization of these values */
+ Qq = video->QPy_div_6;
+ Rq = video->QPy_mod_6;
+
+ memset(video->block, 0, sizeof(int16)*NUM_PIXELS_IN_MB);
+
+ if (currMB->mbMode == AVC_I16)
+ {
+ nC = predict_nnz(video, 0, 0);
+ decvid->residual_block(decvid, nC, 16, level, run, &numcoeff);
+ /* then performs zigzag and transform */
+ block = video->block;
+ coeffNum = -1;
+ for (i = numcoeff - 1; i >= 0; i--)
+ {
+ coeffNum += run[i] + 1;
+ if (coeffNum > 15)
+ {
+ return AVCDEC_FAIL;
+ }
+ idx = zz_scan[coeffNum] << 2;
+ /* idx = ((idx>>2)<<6) + ((idx&3)<<2); */
+ block[idx] = level[i];
+ }
+
+ /* inverse transform on Intra16x16DCLevel */
+ if (numcoeff)
+ {
+ Intra16DCTrans(block, Qq, Rq);
+ cbp4x4 = 0xFFFF;
+ }
+ maxNumCoeff = 15;
+ start_scan = 1;
+ }
+
+ memset(currMB->nz_coeff, 0, sizeof(uint8)*24);
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ mbPartIdx_X = (mbPartIdx & 1) << 1;
+ mbPartIdx_Y = mbPartIdx & -2;
+
+ if (currMB->CBP&(1 << mbPartIdx))
+ {
+ for (subMbPartIdx = 0; subMbPartIdx < 4; subMbPartIdx++)
+ {
+ i = mbPartIdx_X + (subMbPartIdx & 1); // check this
+ j = mbPartIdx_Y + (subMbPartIdx >> 1);
+ block = video->block + (j << 6) + (i << 2); //
+ nC = predict_nnz(video, i, j);
+ decvid->residual_block(decvid, nC, maxNumCoeff, level, run, &numcoeff);
+
+ /* convert to raster scan and quantize*/
+ /* Note: for P mb in SP slice and SI mb in SI slice,
+ the quantization cannot be done here.
+ block[idx] should be assigned with level[k].
+ itrans will be done after the prediction.
+ There will be transformation on the predicted value,
+ then addition with block[idx], then this quantization
+ and transform.*/
+
+ coeffNum = -1 + start_scan;
+ for (k = numcoeff - 1; k >= 0; k--)
+ {
+ coeffNum += run[k] + 1;
+ if (coeffNum > 15)
+ {
+ return AVCDEC_FAIL;
+ }
+ idx = zz_scan[coeffNum];
+ block[idx] = (level[k] * dequant_coefres[Rq][coeffNum]) << Qq ;
+ }
+
+ currMB->nz_coeff[(j<<2)+i] = numcoeff;
+ if (numcoeff)
+ {
+ cbp4x4 |= (1 << ((j << 2) + i));
+ }
+ }
+ }
+ }
+
+ Qq = video->QPc_div_6;
+ Rq = video->QPc_mod_6;
+
+ if (currMB->CBP & (3 << 4)) /* chroma DC residual present */
+ {
+ for (iCbCr = 0; iCbCr < 2; iCbCr++)
+ {
+ decvid->residual_block(decvid, -1, 4, level, run, &numcoeff);
+ block = video->block + 256 + (iCbCr << 3);
+ coeffNum = -1;
+ for (i = numcoeff - 1; i >= 0; i--)
+ {
+ coeffNum += run[i] + 1;
+ if (coeffNum > 3)
+ {
+ return AVCDEC_FAIL;
+ }
+ block[(coeffNum>>1)*64 + (coeffNum&1)*4] = level[i];
+ }
+ /* inverse transform on chroma DC */
+ /* for P in SP and SI in SI, this function can't be done here,
+ must do prediction transform/quant first. */
+ if (numcoeff)
+ {
+ ChromaDCTrans(block, Qq, Rq);
+ cbp4x4 |= (iCbCr ? 0xcc0000 : 0x330000);
+ }
+ }
+ }
+
+ if (currMB->CBP & (2 << 4))
+ {
+ for (block_x = 0; block_x < 4; block_x += 2) /* for iCbCr */
+ {
+ for (j = 4; j < 6; j++) /* for each block inside Cb or Cr */
+ {
+ for (i = block_x; i < block_x + 2; i++)
+ {
+
+ block = video->block + (j << 6) + (i << 2);
+
+ nC = predict_nnz_chroma(video, i, j);
+ decvid->residual_block(decvid, nC, 15, level, run, &numcoeff);
+
+ /* convert to raster scan and quantize */
+ /* for P MB in SP slice and SI MB in SI slice,
+ the dequant and transform cannot be done here.
+ It needs the prediction values. */
+ coeffNum = 0;
+ for (k = numcoeff - 1; k >= 0; k--)
+ {
+ coeffNum += run[k] + 1;
+ if (coeffNum > 15)
+ {
+ return AVCDEC_FAIL;
+ }
+ idx = zz_scan[coeffNum];
+ block[idx] = (level[k] * dequant_coefres[Rq][coeffNum]) << Qq;
+ }
+
+
+ /* then transform */
+ // itrans(block); /* transform */
+ currMB->nz_coeff[(j<<2)+i] = numcoeff; //
+ if (numcoeff)
+ {
+ cbp4x4 |= (1 << ((j << 2) + i));
+ }
+ }
+
+ }
+ }
+ }
+
+ video->cbp4x4 = cbp4x4;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see subclause 7.3.5.3.1 and 9.2 and readCoeff4x4_CAVLC() in JM */
+AVCDec_Status residual_block_cavlc(AVCDecObject *decvid, int nC, int maxNumCoeff,
+ int *level, int *run, int *numcoeff)
+{
+ int i, j;
+ int TrailingOnes, TotalCoeff;
+ AVCDecBitstream *stream = decvid->bitstream;
+ int suffixLength;
+ uint trailing_ones_sign_flag, level_prefix, level_suffix;
+ int levelCode, levelSuffixSize, zerosLeft;
+ int run_before;
+
+
+ if (nC >= 0)
+ {
+ ce_TotalCoeffTrailingOnes(stream, &TrailingOnes, &TotalCoeff, nC);
+ }
+ else
+ {
+ ce_TotalCoeffTrailingOnesChromaDC(stream, &TrailingOnes, &TotalCoeff);
+ }
+
+ *numcoeff = TotalCoeff;
+
+ /* This part is done quite differently in ReadCoef4x4_CAVLC() */
+ if (TotalCoeff == 0)
+ {
+ return AVCDEC_SUCCESS;
+ }
+
+ if (TrailingOnes) /* keep reading the sign of those trailing ones */
+ {
+ /* instead of reading one bit at a time, read the whole thing at once */
+ BitstreamReadBits(stream, TrailingOnes, &trailing_ones_sign_flag);
+ trailing_ones_sign_flag <<= 1;
+ for (i = 0; i < TrailingOnes; i++)
+ {
+ level[i] = 1 - ((trailing_ones_sign_flag >> (TrailingOnes - i - 1)) & 2);
+ }
+ }
+
+ i = TrailingOnes;
+ suffixLength = 1;
+ if (TotalCoeff > TrailingOnes)
+ {
+ ce_LevelPrefix(stream, &level_prefix);
+ if (TotalCoeff < 11 || TrailingOnes == 3)
+ {
+ if (level_prefix < 14)
+ {
+// levelSuffixSize = 0;
+ levelCode = level_prefix;
+ }
+ else if (level_prefix == 14)
+ {
+// levelSuffixSize = 4;
+ BitstreamReadBits(stream, 4, &level_suffix);
+ levelCode = 14 + level_suffix;
+ }
+ else /* if (level_prefix == 15) */
+ {
+// levelSuffixSize = 12;
+ BitstreamReadBits(stream, 12, &level_suffix);
+ levelCode = 30 + level_suffix;
+ }
+ }
+ else
+ {
+ /* suffixLength = 1; */
+ if (level_prefix < 15)
+ {
+ levelSuffixSize = suffixLength;
+ }
+ else
+ {
+ levelSuffixSize = 12;
+ }
+ BitstreamReadBits(stream, levelSuffixSize, &level_suffix);
+
+ levelCode = (level_prefix << 1) + level_suffix;
+ }
+
+ if (TrailingOnes < 3)
+ {
+ levelCode += 2;
+ }
+
+ level[i] = (levelCode + 2) >> 1;
+ if (level[i] > 3)
+ {
+ suffixLength = 2;
+ }
+
+ if (levelCode & 1)
+ {
+ level[i] = -level[i];
+ }
+ i++;
+
+ }
+
+ for (j = TotalCoeff - i; j > 0 ; j--)
+ {
+ ce_LevelPrefix(stream, &level_prefix);
+ if (level_prefix < 15)
+ {
+ levelSuffixSize = suffixLength;
+ }
+ else
+ {
+ levelSuffixSize = 12;
+ }
+ BitstreamReadBits(stream, levelSuffixSize, &level_suffix);
+
+ levelCode = (level_prefix << suffixLength) + level_suffix;
+ level[i] = (levelCode >> 1) + 1;
+ if (level[i] > (3 << (suffixLength - 1)) && suffixLength < 6)
+ {
+ suffixLength++;
+ }
+ if (levelCode & 1)
+ {
+ level[i] = -level[i];
+ }
+ i++;
+ }
+
+
+ if (TotalCoeff < maxNumCoeff)
+ {
+ if (nC >= 0)
+ {
+ ce_TotalZeros(stream, &zerosLeft, TotalCoeff);
+ }
+ else
+ {
+ ce_TotalZerosChromaDC(stream, &zerosLeft, TotalCoeff);
+ }
+ }
+ else
+ {
+ zerosLeft = 0;
+ }
+
+ for (i = 0; i < TotalCoeff - 1; i++)
+ {
+ if (zerosLeft > 0)
+ {
+ ce_RunBefore(stream, &run_before, zerosLeft);
+ run[i] = run_before;
+ }
+ else
+ {
+ run[i] = 0;
+ zerosLeft = 0; // could be negative under error conditions
+ }
+
+ zerosLeft = zerosLeft - run[i];
+ }
+
+ if (zerosLeft < 0)
+ {
+ zerosLeft = 0;
+// return AVCDEC_FAIL;
+ }
+
+ run[TotalCoeff-1] = zerosLeft;
+
+ /* leave the inverse zigzag scan part for the caller */
+
+
+ return AVCDEC_SUCCESS;
+}
diff --git a/media/libstagefright/codecs/avc/dec/src/slice.cpp b/media/libstagefright/codecs/avc/dec/src/slice.cpp
new file mode 100644
index 0000000..7a2ef3d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/slice.cpp
@@ -0,0 +1,772 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/* Note for optimization: syntax decoding or operations related to B_SLICE should be
+commented out by macro definition or function pointers. */
+
+#include <string.h>
+
+#include "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+
+const static int mbPart2raster[3][4] = {{0, 0, 0, 0}, {1, 1, 0, 0}, {1, 0, 1, 0}};
+/* decode_frame_slice() */
+/* decode_one_slice() */
+AVCDec_Status DecodeSlice(AVCDecObject *decvid)
+{
+ AVCDec_Status status;
+ AVCCommonObj *video = decvid->common;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCMacroblock *currMB ;
+ AVCDecBitstream *stream = decvid->bitstream;
+ uint slice_group_id;
+ uint CurrMbAddr, moreDataFlag;
+
+ /* set the first mb in slice */
+ CurrMbAddr = sliceHdr->first_mb_in_slice;
+ slice_group_id = video->MbToSliceGroupMap[CurrMbAddr];
+
+ if ((CurrMbAddr && (CurrMbAddr != (uint)(video->mbNum + 1))) && video->currSeqParams->constrained_set1_flag == 1)
+ {
+ ConcealSlice(decvid, video->mbNum, CurrMbAddr);
+ }
+
+ moreDataFlag = 1;
+ video->mb_skip_run = -1;
+
+
+ /* while loop , see subclause 7.3.4 */
+ do
+ {
+ if (CurrMbAddr >= video->PicSizeInMbs)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ currMB = video->currMB = &(video->mblock[CurrMbAddr]);
+ video->mbNum = CurrMbAddr;
+ currMB->slice_id = video->slice_id; // slice
+
+ /* we can remove this check if we don't support Mbaff. */
+ /* we can wrap below into an initMB() function which will also
+ do necessary reset of macroblock related parameters. */
+
+ video->mb_x = CurrMbAddr % video->PicWidthInMbs;
+ video->mb_y = CurrMbAddr / video->PicWidthInMbs;
+
+ /* check the availability of neighboring macroblocks */
+ InitNeighborAvailability(video, CurrMbAddr);
+
+ /* read_macroblock and decode_one_macroblock() */
+ status = DecodeMB(decvid);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+#ifdef MB_BASED_DEBLOCK
+ if (video->currPicParams->num_slice_groups_minus1 == 0)
+ {
+ MBInLoopDeblock(video); /* MB-based deblocking */
+ }
+ else /* this mode cannot be used if the number of slice group is not one. */
+ {
+ return AVCDEC_FAIL;
+ }
+#endif
+ video->numMBs--;
+
+ moreDataFlag = more_rbsp_data(stream);
+
+
+ /* go to next MB */
+ while (++CurrMbAddr < video->PicSizeInMbs && video->MbToSliceGroupMap[CurrMbAddr] != (int)slice_group_id)
+ {
+ }
+
+ }
+ while ((moreDataFlag && video->numMBs > 0) || video->mb_skip_run > 0); /* even if no more data, but last few MBs are skipped */
+
+ if (video->numMBs == 0)
+ {
+ video->newPic = TRUE;
+ video->mbNum = 0; // _Conceal
+ return AVCDEC_PICTURE_READY;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* read MB mode and motion vectors */
+/* perform Intra/Inter prediction and residue */
+/* update video->mb_skip_run */
+AVCDec_Status DecodeMB(AVCDecObject *decvid)
+{
+ AVCDec_Status status;
+ AVCCommonObj *video = decvid->common;
+ AVCDecBitstream *stream = decvid->bitstream;
+ AVCMacroblock *currMB = video->currMB;
+ uint mb_type;
+ int slice_type = video->slice_type;
+ int temp;
+
+ currMB->QPy = video->QPy;
+ currMB->QPc = video->QPc;
+
+ if (slice_type == AVC_P_SLICE)
+ {
+ if (video->mb_skip_run < 0)
+ {
+ ue_v(stream, (uint *)&(video->mb_skip_run));
+ }
+
+ if (video->mb_skip_run == 0)
+ {
+ /* this will not handle the case where the slice ends with a mb_skip_run == 0 and no following MB data */
+ ue_v(stream, &mb_type);
+ if (mb_type > 30)
+ {
+ return AVCDEC_FAIL;
+ }
+ InterpretMBModeP(currMB, mb_type);
+ video->mb_skip_run = -1;
+ }
+ else
+ {
+ /* see subclause 7.4.4 for more details on how
+ mb_field_decoding_flag is derived in case of skipped MB */
+
+ currMB->mb_intra = FALSE;
+
+ currMB->mbMode = AVC_SKIP;
+ currMB->MbPartWidth = currMB->MbPartHeight = 16;
+ currMB->NumMbPart = 1;
+ currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
+ currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1; //
+ currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
+ currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
+ currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
+ currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
+
+ memset(currMB->nz_coeff, 0, sizeof(uint8)*NUM_BLKS_IN_MB);
+
+ currMB->CBP = 0;
+ video->cbp4x4 = 0;
+ /* for skipped MB, always look at the first entry in RefPicList */
+ currMB->RefIdx[0] = currMB->RefIdx[1] =
+ currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
+ InterMBPrediction(video);
+ video->mb_skip_run--;
+ return AVCDEC_SUCCESS;
+ }
+
+ }
+ else
+ {
+ /* Then decode mode and MV */
+ ue_v(stream, &mb_type);
+ if (mb_type > 25)
+ {
+ return AVCDEC_FAIL;
+ }
+ InterpretMBModeI(currMB, mb_type);
+ }
+
+
+ if (currMB->mbMode != AVC_I_PCM)
+ {
+
+ if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
+ {
+ status = sub_mb_pred(video, currMB, stream);
+ }
+ else
+ {
+ status = mb_pred(video, currMB, stream) ;
+ }
+
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+
+ if (currMB->mbMode != AVC_I16)
+ {
+ /* decode coded_block_pattern */
+ status = DecodeCBP(currMB, stream);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ if (currMB->CBP > 0 || currMB->mbMode == AVC_I16)
+ {
+ se_v(stream, &temp);
+ if (temp)
+ {
+ temp += (video->QPy + 52);
+ currMB->QPy = video->QPy = temp - 52 * (temp * 79 >> 12);
+ if (currMB->QPy > 51 || currMB->QPy < 0)
+ {
+ video->QPy = AVC_CLIP3(0, 51, video->QPy);
+// return AVCDEC_FAIL;
+ }
+ video->QPy_div_6 = (video->QPy * 43) >> 8;
+ video->QPy_mod_6 = video->QPy - 6 * video->QPy_div_6;
+ currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->QPy + video->currPicParams->chroma_qp_index_offset)];
+ video->QPc_div_6 = (video->QPc * 43) >> 8;
+ video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
+ }
+ }
+ /* decode residue and inverse transform */
+ status = residual(decvid, currMB);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ else
+ {
+ if (stream->bitcnt & 7)
+ {
+ BitstreamByteAlign(stream);
+ }
+ /* decode pcm_byte[i] */
+ DecodeIntraPCM(video, stream);
+
+ currMB->QPy = 0; /* necessary for deblocking */ // _OPTIMIZE
+ currMB->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->currPicParams->chroma_qp_index_offset)];
+
+ /* default values, don't know if really needed */
+ currMB->CBP = 0x3F;
+ video->cbp4x4 = 0xFFFF;
+ currMB->mb_intra = TRUE;
+ memset(currMB->nz_coeff, 16, sizeof(uint8)*NUM_BLKS_IN_MB);
+ return AVCDEC_SUCCESS;
+ }
+
+
+ /* do Intra/Inter prediction, together with the residue compensation */
+ /* This part should be common between the skip and no-skip */
+ if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
+ {
+ IntraMBPrediction(video);
+ }
+ else
+ {
+ InterMBPrediction(video);
+ }
+
+
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see subclause 7.3.5.1 */
+AVCDec_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
+{
+ int mbPartIdx;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ uint max_ref_idx;
+ const int *temp_0;
+ int16 *temp_1;
+ uint code;
+
+ if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
+ {
+
+ video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+
+ if (!video->currPicParams->constrained_intra_pred_flag)
+ {
+ video->intraAvailA = video->mbAvailA;
+ video->intraAvailB = video->mbAvailB;
+ video->intraAvailC = video->mbAvailC;
+ video->intraAvailD = video->mbAvailD;
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+ }
+ if (video->mbAvailB)
+ {
+ video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+ }
+ if (video->mbAvailC)
+ {
+ video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+ }
+ if (video->mbAvailD)
+ {
+ video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+ }
+ }
+
+
+ if (currMB->mbMode == AVC_I4)
+ {
+ /* perform prediction to get the actual intra 4x4 pred mode */
+ DecodeIntra4x4Mode(video, currMB, stream);
+ /* output will be in currMB->i4Mode[4][4] */
+ }
+
+ ue_v(stream, &code);
+
+ if (code > 3)
+ {
+ return AVCDEC_FAIL; /* out of range */
+ }
+ currMB->intra_chroma_pred_mode = (AVCIntraChromaPredMode)code;
+ }
+ else
+ {
+
+ memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+// max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+ max_ref_idx = video->refList0Size - 1;
+
+ /* decode ref index for L0 */
+ if (sliceHdr->num_ref_idx_l0_active_minus1 > 0)
+ {
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ te_v(stream, &code, max_ref_idx);
+ if (code > (uint)max_ref_idx)
+ {
+ return AVCDEC_FAIL;
+ }
+ currMB->ref_idx_L0[mbPartIdx] = code;
+ }
+ }
+
+ /* populate ref_idx_L0 */
+ temp_0 = &mbPart2raster[currMB->mbMode-AVC_P16][0];
+ temp_1 = &currMB->ref_idx_L0[3];
+
+ *temp_1-- = currMB->ref_idx_L0[*temp_0++];
+ *temp_1-- = currMB->ref_idx_L0[*temp_0++];
+ *temp_1-- = currMB->ref_idx_L0[*temp_0++];
+ *temp_1-- = currMB->ref_idx_L0[*temp_0++];
+
+ /* Global reference index, these values are used in deblock */
+ currMB->RefIdx[0] = video->RefPicList0[currMB->ref_idx_L0[0]]->RefIdx;
+ currMB->RefIdx[1] = video->RefPicList0[currMB->ref_idx_L0[1]]->RefIdx;
+ currMB->RefIdx[2] = video->RefPicList0[currMB->ref_idx_L0[2]]->RefIdx;
+ currMB->RefIdx[3] = video->RefPicList0[currMB->ref_idx_L0[3]]->RefIdx;
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+ max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+ /* decode mvd_l0 */
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ se_v(stream, &(video->mvd_l0[mbPartIdx][0][0]));
+ se_v(stream, &(video->mvd_l0[mbPartIdx][0][1]));
+ }
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see subclause 7.3.5.2 */
+AVCDec_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
+{
+ int mbPartIdx, subMbPartIdx;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ uint max_ref_idx;
+ uint sub_mb_type[4];
+ uint code;
+
+ memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ ue_v(stream, &(sub_mb_type[mbPartIdx]));
+ if (sub_mb_type[mbPartIdx] > 3)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ }
+ /* we have to check the values to make sure they are valid */
+ /* assign values to currMB->sub_mb_type[], currMB->MBPartPredMode[][x] */
+
+ InterpretSubMBModeP(currMB, sub_mb_type);
+
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+// max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+ max_ref_idx = video->refList0Size - 1;
+
+ if (sliceHdr->num_ref_idx_l0_active_minus1 > 0 && currMB->mbMode != AVC_P8ref0)
+ {
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ te_v(stream, (uint*)&code, max_ref_idx);
+ if (code > max_ref_idx)
+ {
+ return AVCDEC_FAIL;
+ }
+ currMB->ref_idx_L0[mbPartIdx] = code;
+ }
+ }
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+
+ max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+ /* if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+ max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;*/
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ se_v(stream, &(video->mvd_l0[mbPartIdx][subMbPartIdx][0]));
+ se_v(stream, &(video->mvd_l0[mbPartIdx][subMbPartIdx][1]));
+ }
+ /* used in deblocking */
+ currMB->RefIdx[mbPartIdx] = video->RefPicList0[currMB->ref_idx_L0[mbPartIdx]]->RefIdx;
+ }
+ return AVCDEC_SUCCESS;
+}
+
+void InterpretMBModeI(AVCMacroblock *mblock, uint mb_type)
+{
+ mblock->NumMbPart = 1;
+
+ mblock->mb_intra = TRUE;
+
+ if (mb_type == 0) /* I_4x4 */
+ {
+ mblock->mbMode = AVC_I4;
+ }
+ else if (mb_type < 25) /* I_PCM */
+ {
+ mblock->mbMode = AVC_I16;
+ mblock->i16Mode = (AVCIntra16x16PredMode)((mb_type - 1) & 0x3);
+ if (mb_type > 12)
+ {
+ mblock->CBP = (((mb_type - 13) >> 2) << 4) + 0x0F;
+ }
+ else
+ {
+ mblock->CBP = ((mb_type - 1) >> 2) << 4;
+ }
+ }
+ else
+ {
+ mblock->mbMode = AVC_I_PCM;
+ }
+
+ return ;
+}
+
+void InterpretMBModeP(AVCMacroblock *mblock, uint mb_type)
+{
+ const static int map2PartWidth[5] = {16, 16, 8, 8, 8};
+ const static int map2PartHeight[5] = {16, 8, 16, 8, 8};
+ const static int map2NumPart[5] = {1, 2, 2, 4, 4};
+ const static AVCMBMode map2mbMode[5] = {AVC_P16, AVC_P16x8, AVC_P8x16, AVC_P8, AVC_P8ref0};
+
+ mblock->mb_intra = FALSE;
+ if (mb_type < 5)
+ {
+ mblock->mbMode = map2mbMode[mb_type];
+ mblock->MbPartWidth = map2PartWidth[mb_type];
+ mblock->MbPartHeight = map2PartHeight[mb_type];
+ mblock->NumMbPart = map2NumPart[mb_type];
+ mblock->NumSubMbPart[0] = mblock->NumSubMbPart[1] =
+ mblock->NumSubMbPart[2] = mblock->NumSubMbPart[3] = 1;
+ mblock->SubMbPartWidth[0] = mblock->SubMbPartWidth[1] =
+ mblock->SubMbPartWidth[2] = mblock->SubMbPartWidth[3] = mblock->MbPartWidth;
+ mblock->SubMbPartHeight[0] = mblock->SubMbPartHeight[1] =
+ mblock->SubMbPartHeight[2] = mblock->SubMbPartHeight[3] = mblock->MbPartHeight;
+ }
+ else
+ {
+ InterpretMBModeI(mblock, mb_type - 5);
+ /* set MV and Ref_Idx codes of Intra blocks in P-slices */
+ memset(mblock->mvL0, 0, sizeof(int32)*16);
+ mblock->ref_idx_L0[0] = mblock->ref_idx_L0[1] = mblock->ref_idx_L0[2] = mblock->ref_idx_L0[3] = -1;
+ }
+ return ;
+}
+
+void InterpretMBModeB(AVCMacroblock *mblock, uint mb_type)
+{
+ const static int map2PartWidth[23] = {8, 16, 16, 16, 16, 8, 16, 8, 16, 8,
+ 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 8
+ };
+ const static int map2PartHeight[23] = {8, 16, 16, 16, 8, 16, 8, 16, 8,
+ 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8
+ };
+ /* see enum AVCMBType declaration */
+ const static AVCMBMode map2mbMode[23] = {AVC_BDirect16, AVC_P16, AVC_P16, AVC_P16,
+ AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16,
+ AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16,
+ AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P8
+ };
+ const static int map2PredMode1[23] = {3, 0, 1, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, -1};
+ const static int map2PredMode2[23] = { -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, -1};
+ const static int map2NumPart[23] = { -1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4};
+
+ mblock->mb_intra = FALSE;
+
+ if (mb_type < 23)
+ {
+ mblock->mbMode = map2mbMode[mb_type];
+ mblock->NumMbPart = map2NumPart[mb_type];
+ mblock->MBPartPredMode[0][0] = (AVCPredMode)map2PredMode1[mb_type];
+ if (mblock->NumMbPart > 1)
+ {
+ mblock->MBPartPredMode[1][0] = (AVCPredMode)map2PredMode2[mb_type];
+ }
+ mblock->MbPartWidth = map2PartWidth[mb_type];
+ mblock->MbPartHeight = map2PartHeight[mb_type];
+ }
+ else
+ {
+ InterpretMBModeI(mblock, mb_type - 23);
+ }
+
+ return ;
+}
+
+void InterpretMBModeSI(AVCMacroblock *mblock, uint mb_type)
+{
+ mblock->mb_intra = TRUE;
+
+ if (mb_type == 0)
+ {
+ mblock->mbMode = AVC_SI4;
+ /* other values are N/A */
+ }
+ else
+ {
+ InterpretMBModeI(mblock, mb_type - 1);
+ }
+ return ;
+}
+
+/* input is mblock->sub_mb_type[] */
+void InterpretSubMBModeP(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+ int i, sub_type;
+ /* see enum AVCMBType declaration */
+// const static AVCSubMBMode map2subMbMode[4] = {AVC_8x8,AVC_8x4,AVC_4x8,AVC_4x4};
+ const static int map2subPartWidth[4] = {8, 8, 4, 4};
+ const static int map2subPartHeight[4] = {8, 4, 8, 4};
+ const static int map2numSubPart[4] = {1, 2, 2, 4};
+
+ for (i = 0; i < 4 ; i++)
+ {
+ sub_type = (int) sub_mb_type[i];
+ // mblock->subMbMode[i] = map2subMbMode[sub_type];
+ mblock->NumSubMbPart[i] = map2numSubPart[sub_type];
+ mblock->SubMbPartWidth[i] = map2subPartWidth[sub_type];
+ mblock->SubMbPartHeight[i] = map2subPartHeight[sub_type];
+ }
+
+ return ;
+}
+
+void InterpretSubMBModeB(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+ int i, j, sub_type;
+ /* see enum AVCMBType declaration */
+ const static AVCSubMBMode map2subMbMode[13] = {AVC_BDirect8, AVC_8x8, AVC_8x8,
+ AVC_8x8, AVC_8x4, AVC_4x8, AVC_8x4, AVC_4x8, AVC_8x4, AVC_4x8, AVC_4x4, AVC_4x4, AVC_4x4
+ };
+ const static int map2subPartWidth[13] = {4, 8, 8, 8, 8, 4, 8, 4, 8, 4, 4, 4, 4};
+ const static int map2subPartHeight[13] = {4, 8, 8, 8, 4, 8, 4, 8, 4, 8, 4, 4, 4};
+ const static int map2numSubPart[13] = {1, 1, 1, 2, 2, 2, 2, 2, 2, 4, 4, 4};
+ const static int map2predMode[13] = {3, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2};
+
+ for (i = 0; i < 4 ; i++)
+ {
+ sub_type = (int) sub_mb_type[i];
+ mblock->subMbMode[i] = map2subMbMode[sub_type];
+ mblock->NumSubMbPart[i] = map2numSubPart[sub_type];
+ mblock->SubMbPartWidth[i] = map2subPartWidth[sub_type];
+ mblock->SubMbPartHeight[i] = map2subPartHeight[sub_type];
+ for (j = 0; j < 4; j++)
+ {
+ mblock->MBPartPredMode[i][j] = (AVCPredMode)map2predMode[sub_type];
+ }
+ }
+
+ return ;
+}
+
+/* see subclause 8.3.1 */
+AVCDec_Status DecodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
+{
+ int intra4x4PredModeA = 0, intra4x4PredModeB = 0, predIntra4x4PredMode = 0;
+ int component, SubBlock_indx, block_x, block_y;
+ int dcOnlyPredictionFlag;
+ uint prev_intra4x4_pred_mode_flag[16];
+ int rem_intra4x4_pred_mode[16];
+ int bindx = 0;
+
+ for (component = 0; component < 4; component++) /* partition index */
+ {
+ block_x = ((component & 1) << 1);
+ block_y = ((component >> 1) << 1);
+
+ for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++) /* sub-partition index */
+ {
+ BitstreamRead1Bit(stream, &(prev_intra4x4_pred_mode_flag[bindx]));
+
+ if (!prev_intra4x4_pred_mode_flag[bindx])
+ {
+ BitstreamReadBits(stream, 3, (uint*)&(rem_intra4x4_pred_mode[bindx]));
+ }
+
+ dcOnlyPredictionFlag = 0;
+ if (block_x > 0)
+ {
+ intra4x4PredModeA = currMB->i4Mode[(block_y << 2) + block_x - 1 ];
+ }
+ else
+ {
+ if (video->intraAvailA)
+ {
+ if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
+ {
+ intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[(block_y << 2) + 3];
+ }
+ else
+ {
+ intra4x4PredModeA = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ }
+ }
+
+ if (block_y > 0)
+ {
+ intra4x4PredModeB = currMB->i4Mode[((block_y-1) << 2) + block_x];
+ }
+ else
+ {
+ if (video->intraAvailB)
+ {
+ if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
+ {
+ intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[(3 << 2) + block_x];
+ }
+ else
+ {
+ intra4x4PredModeB = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ }
+ }
+
+ if (dcOnlyPredictionFlag)
+ {
+ intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
+ }
+
+ predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
+ if (prev_intra4x4_pred_mode_flag[bindx])
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)predIntra4x4PredMode;
+ }
+ else
+ {
+ if (rem_intra4x4_pred_mode[bindx] < predIntra4x4PredMode)
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)rem_intra4x4_pred_mode[bindx];
+ }
+ else
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)(rem_intra4x4_pred_mode[bindx] + 1);
+ }
+ }
+ bindx++;
+ block_y += (SubBlock_indx & 1) ;
+ block_x += (1 - 2 * (SubBlock_indx & 1)) ;
+ }
+ }
+ return AVCDEC_SUCCESS;
+}
+AVCDec_Status ConcealSlice(AVCDecObject *decvid, int mbnum_start, int mbnum_end)
+{
+ AVCCommonObj *video = decvid->common;
+ AVCMacroblock *currMB ;
+
+ int CurrMbAddr;
+
+ if (video->RefPicList0[0] == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ for (CurrMbAddr = mbnum_start; CurrMbAddr < mbnum_end; CurrMbAddr++)
+ {
+ currMB = video->currMB = &(video->mblock[CurrMbAddr]);
+ video->mbNum = CurrMbAddr;
+ currMB->slice_id = video->slice_id++; // slice
+
+ /* we can remove this check if we don't support Mbaff. */
+ /* we can wrap below into an initMB() function which will also
+ do necessary reset of macroblock related parameters. */
+
+ video->mb_x = CurrMbAddr % video->PicWidthInMbs;
+ video->mb_y = CurrMbAddr / video->PicWidthInMbs;
+
+ /* check the availability of neighboring macroblocks */
+ InitNeighborAvailability(video, CurrMbAddr);
+
+ currMB->mb_intra = FALSE;
+
+ currMB->mbMode = AVC_SKIP;
+ currMB->MbPartWidth = currMB->MbPartHeight = 16;
+
+ currMB->NumMbPart = 1;
+ currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
+ currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1;
+ currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
+ currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
+ currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
+ currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
+ currMB->QPy = 26;
+ currMB->QPc = 26;
+ memset(currMB->nz_coeff, 0, sizeof(uint8)*NUM_BLKS_IN_MB);
+
+ currMB->CBP = 0;
+ video->cbp4x4 = 0;
+ /* for skipped MB, always look at the first entry in RefPicList */
+ currMB->RefIdx[0] = currMB->RefIdx[1] =
+ currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
+ InterMBPrediction(video);
+
+ video->numMBs--;
+
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/dec/src/vlc.cpp b/media/libstagefright/codecs/avc/dec/src/vlc.cpp
new file mode 100644
index 0000000..f531249
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/vlc.cpp
@@ -0,0 +1,815 @@
+/* ------------------------------------------------------------------
+ * 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 "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+
+//#define PV_ARM_V5
+#ifdef PV_ARM_V5
+#define PV_CLZ(A,B) __asm{CLZ (A),(B)} \
+ A -= 16;
+#else
+#define PV_CLZ(A,B) while (((B) & 0x8000) == 0) {(B) <<=1; A++;}
+#endif
+
+
+#define PV_NO_CLZ
+
+#ifndef PV_NO_CLZ
+typedef struct tagVLCNumCoeffTrail
+{
+ int trailing;
+ int total_coeff;
+ int length;
+} VLCNumCoeffTrail;
+
+typedef struct tagShiftOffset
+{
+ int shift;
+ int offset;
+} ShiftOffset;
+
+const VLCNumCoeffTrail NumCoeffTrailOnes[3][67] =
+{
+ {{0, 0, 1}, {1, 1, 2}, {2, 2, 3}, {1, 2, 6}, {0, 1, 6}, {3, 3, 5}, {3, 3, 5}, {3, 5, 7},
+ {2, 3, 7}, {3, 4, 6}, {3, 4, 6}, {3, 6, 8}, {2, 4, 8}, {1, 3, 8}, {0, 2, 8}, {3, 7, 9},
+ {2, 5, 9}, {1, 4, 9}, {0, 3, 9}, {3, 8, 10}, {2, 6, 10}, {1, 5, 10}, {0, 4, 10}, {3, 9, 11},
+ {2, 7, 11}, {1, 6, 11}, {0, 5, 11}, {0, 8, 13}, {2, 9, 13}, {1, 8, 13}, {0, 7, 13}, {3, 10, 13},
+ {2, 8, 13}, {1, 7, 13}, {0, 6, 13}, {3, 12, 14}, {2, 11, 14}, {1, 10, 14}, {0, 10, 14}, {3, 11, 14},
+ {2, 10, 14}, {1, 9, 14}, {0, 9, 14}, {3, 14, 15}, {2, 13, 15}, {1, 12, 15}, {0, 12, 15}, {3, 13, 15},
+ {2, 12, 15}, {1, 11, 15}, {0, 11, 15}, {3, 16, 16}, {2, 15, 16}, {1, 15, 16}, {0, 14, 16}, {3, 15, 16},
+ {2, 14, 16}, {1, 14, 16}, {0, 13, 16}, {0, 16, 16}, {2, 16, 16}, {1, 16, 16}, {0, 15, 16}, {1, 13, 15},
+ { -1, -1, -1}, { -1, -1, -1}, { -1, -1, -1}},
+
+ {{1, 1, 2}, {0, 0, 2}, {3, 4, 4}, {3, 3, 4}, {2, 2, 3}, {2, 2, 3}, {3, 6, 6}, {2, 3, 6},
+ {1, 3, 6}, {0, 1, 6}, {3, 5, 5}, {3, 5, 5}, {1, 2, 5}, {1, 2, 5}, {3, 7, 6}, {2, 4, 6},
+ {1, 4, 6}, {0, 2, 6}, {3, 8, 7}, {2, 5, 7}, {1, 5, 7}, {0, 3, 7}, {0, 5, 8}, {2, 6, 8},
+ {1, 6, 8}, {0, 4, 8}, {3, 9, 9}, {2, 7, 9}, {1, 7, 9}, {0, 6, 9}, {3, 11, 11}, {2, 9, 11},
+ {1, 9, 11}, {0, 8, 11}, {3, 10, 11}, {2, 8, 11}, {1, 8, 11}, {0, 7, 11}, {0, 11, 12}, {2, 11, 12},
+ {1, 11, 12}, {0, 10, 12}, {3, 12, 12}, {2, 10, 12}, {1, 10, 12}, {0, 9, 12}, {3, 14, 13}, {2, 13, 13},
+ {1, 13, 13}, {0, 13, 13}, {3, 13, 13}, {2, 12, 13}, {1, 12, 13}, {0, 12, 13}, {1, 15, 14}, {0, 15, 14},
+ {2, 15, 14}, {1, 14, 14}, {2, 14, 13}, {2, 14, 13}, {0, 14, 13}, {0, 14, 13}, {3, 16, 14}, {2, 16, 14},
+ {1, 16, 14}, {0, 16, 14}, {3, 15, 13}},
+
+ {{3, 7, 4}, {3, 6, 4}, {3, 5, 4}, {3, 4, 4}, {3, 3, 4}, {2, 2, 4}, {1, 1, 4}, {0, 0, 4},
+ {1, 5, 5}, {2, 5, 5}, {1, 4, 5}, {2, 4, 5}, {1, 3, 5}, {3, 8, 5}, {2, 3, 5}, {1, 2, 5},
+ {0, 3, 6}, {2, 7, 6}, {1, 7, 6}, {0, 2, 6}, {3, 9, 6}, {2, 6, 6}, {1, 6, 6}, {0, 1, 6},
+ {0, 7, 7}, {0, 6, 7}, {2, 9, 7}, {0, 5, 7}, {3, 10, 7}, {2, 8, 7}, {1, 8, 7}, {0, 4, 7},
+ {3, 12, 8}, {2, 11, 8}, {1, 10, 8}, {0, 9, 8}, {3, 11, 8}, {2, 10, 8}, {1, 9, 8}, {0, 8, 8},
+ {0, 12, 9}, {2, 13, 9}, {1, 12, 9}, {0, 11, 9}, {3, 13, 9}, {2, 12, 9}, {1, 11, 9}, {0, 10, 9},
+ {1, 15, 10}, {0, 14, 10}, {3, 14, 10}, {2, 14, 10}, {1, 14, 10}, {0, 13, 10}, {1, 13, 9}, {1, 13, 9},
+ {1, 16, 10}, {0, 15, 10}, {3, 15, 10}, {2, 15, 10}, {3, 16, 10}, {2, 16, 10}, {0, 16, 10}, { -1, -1, -1},
+ { -1, -1, -1}, { -1, -1, -1}, { -1, -1, -1}}
+};
+
+
+const ShiftOffset NumCoeffTrailOnes_indx[3][15] =
+{
+ {{15, -1}, {14, 0}, {13, 1}, {10, -1}, {9, 3}, {8, 7}, {7, 11}, {6, 15},
+ {5, 19}, {3, 19}, {2, 27}, {1, 35}, {0, 43}, {0, 55}, {1, 62}},
+
+ {{14, -2}, {12, -2}, {10, -2}, {10, 10}, {9, 14}, {8, 18}, {7, 22}, {5, 22},
+ {4, 30}, {3, 38}, {2, 46}, {2, 58}, {3, 65}, {16, 0}, {16, 0}},
+
+ {{12, -8}, {11, 0}, {10, 8}, {9, 16}, {8, 24}, {7, 32}, {6, 40}, {6, 52},
+ {6, 58}, {6, 61}, {16, 0}, {16, 0}, {16, 0}, {16, 0}, {16, 0}}
+};
+
+const static int nC_table[8] = {0, 0, 1, 1, 2, 2, 2, 2};
+
+#endif
+/**
+See algorithm in subclause 9.1, Table 9-1, Table 9-2. */
+AVCDec_Status ue_v(AVCDecBitstream *bitstream, uint *codeNum)
+{
+ uint temp, tmp_cnt;
+ int leading_zeros = 0;
+ BitstreamShowBits(bitstream, 16, &temp);
+ tmp_cnt = temp | 0x1;
+
+ PV_CLZ(leading_zeros, tmp_cnt)
+
+ if (leading_zeros < 8)
+ {
+ *codeNum = (temp >> (15 - (leading_zeros << 1))) - 1;
+ BitstreamFlushBits(bitstream, (leading_zeros << 1) + 1);
+ }
+ else
+ {
+ BitstreamReadBits(bitstream, (leading_zeros << 1) + 1, &temp);
+ *codeNum = temp - 1;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/**
+See subclause 9.1.1, Table 9-3 */
+AVCDec_Status se_v(AVCDecBitstream *bitstream, int *value)
+{
+ uint temp, tmp_cnt;
+ int leading_zeros = 0;
+ BitstreamShowBits(bitstream, 16, &temp);
+ tmp_cnt = temp | 0x1;
+
+ PV_CLZ(leading_zeros, tmp_cnt)
+
+ if (leading_zeros < 8)
+ {
+ temp >>= (15 - (leading_zeros << 1));
+ BitstreamFlushBits(bitstream, (leading_zeros << 1) + 1);
+ }
+ else
+ {
+ BitstreamReadBits(bitstream, (leading_zeros << 1) + 1, &temp);
+ }
+
+ *value = temp >> 1;
+
+ if (temp & 0x01) // lsb is signed bit
+ *value = -(*value);
+
+// leading_zeros = temp >> 1;
+// *value = leading_zeros - (leading_zeros*2*(temp&1));
+
+ return AVCDEC_SUCCESS;
+}
+
+AVCDec_Status se_v32bit(AVCDecBitstream *bitstream, int32 *value)
+{
+ int leadingZeros;
+ uint32 infobits;
+ uint32 codeNum;
+
+ if (AVCDEC_SUCCESS != GetEGBitstring32bit(bitstream, &leadingZeros, &infobits))
+ return AVCDEC_FAIL;
+
+ codeNum = (1 << leadingZeros) - 1 + infobits;
+
+ *value = (codeNum + 1) / 2;
+
+ if ((codeNum & 0x01) == 0) // lsb is signed bit
+ *value = -(*value);
+
+ return AVCDEC_SUCCESS;
+}
+
+
+AVCDec_Status te_v(AVCDecBitstream *bitstream, uint *value, uint range)
+{
+ if (range > 1)
+ {
+ ue_v(bitstream, value);
+ }
+ else
+ {
+ BitstreamRead1Bit(bitstream, value);
+ *value = 1 - (*value);
+ }
+ return AVCDEC_SUCCESS;
+}
+
+
+
+/* This function is only used for syntax with range from -2^31 to 2^31-1 */
+/* only a few of them in the SPS and PPS */
+AVCDec_Status GetEGBitstring32bit(AVCDecBitstream *bitstream, int *leadingZeros, uint32 *infobits)
+{
+ int bit_value;
+ uint info_temp;
+
+ *leadingZeros = 0;
+
+ BitstreamRead1Bit(bitstream, (uint*)&bit_value);
+
+ while (!bit_value)
+ {
+ (*leadingZeros)++;
+ BitstreamRead1Bit(bitstream, (uint*)&bit_value);
+ }
+
+ if (*leadingZeros > 0)
+ {
+ if (sizeof(uint) == 4) /* 32 bit machine */
+ {
+ BitstreamReadBits(bitstream, *leadingZeros, (uint*)&info_temp);
+ *infobits = (uint32)info_temp;
+ }
+ else if (sizeof(uint) == 2) /* 16 bit machine */
+ {
+ *infobits = 0;
+ if (*leadingZeros > 16)
+ {
+ BitstreamReadBits(bitstream, 16, (uint*)&info_temp);
+ (*leadingZeros) -= 16;
+ *infobits = ((uint32)info_temp) << (*leadingZeros);
+ }
+
+ BitstreamReadBits(bitstream, *leadingZeros, (uint*)&info_temp);
+ *infobits |= (uint32)info_temp ;
+ }
+ }
+ else
+ *infobits = 0;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see Table 9-4 assignment of codeNum to values of coded_block_pattern. */
+const static uint8 MapCBP[48][2] =
+{
+ {47, 0}, {31, 16}, {15, 1}, { 0, 2}, {23, 4}, {27, 8}, {29, 32}, {30, 3}, { 7, 5}, {11, 10}, {13, 12}, {14, 15},
+ {39, 47}, {43, 7}, {45, 11}, {46, 13}, {16, 14}, { 3, 6}, { 5, 9}, {10, 31}, {12, 35}, {19, 37}, {21, 42}, {26, 44},
+ {28, 33}, {35, 34}, {37, 36}, {42, 40}, {44, 39}, { 1, 43}, { 2, 45}, { 4, 46}, { 8, 17}, {17, 18}, {18, 20}, {20, 24},
+ {24, 19}, { 6, 21}, { 9, 26}, {22, 28}, {25, 23}, {32, 27}, {33, 29}, {34, 30}, {36, 22}, {40, 25}, {38, 38}, {41, 41},
+};
+
+AVCDec_Status DecodeCBP(AVCMacroblock *currMB, AVCDecBitstream *stream)
+{
+ uint codeNum;
+ uint coded_block_pattern;
+
+ ue_v(stream, &codeNum);
+
+ if (codeNum > 47)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* can get rid of the if _OPTIMIZE */
+ if (currMB->mbMode == AVC_I4)
+ {
+ coded_block_pattern = MapCBP[codeNum][0];
+ }
+ else
+ {
+ coded_block_pattern = MapCBP[codeNum][1];
+ }
+
+// currMB->cbpL = coded_block_pattern&0xF; /* modulo 16 */
+// currMB->cbpC = coded_block_pattern>>4; /* divide 16 */
+ currMB->CBP = coded_block_pattern;
+
+ return AVCDEC_SUCCESS;
+}
+
+
+/* TO BE OPTIMIZED !!!!! */
+AVCDec_Status ce_TotalCoeffTrailingOnes(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff, int nC)
+{
+#ifdef PV_NO_CLZ
+ const static uint8 TotCofNTrail1[75][3] = {{0, 0, 16}/*error */, {0, 0, 16}/*error */, {1, 13, 15}, {1, 13, 15}, {0, 16, 16}, {2, 16, 16}, {1, 16, 16}, {0, 15, 16},
+ {3, 16, 16}, {2, 15, 16}, {1, 15, 16}, {0, 14, 16}, {3, 15, 16}, {2, 14, 16}, {1, 14, 16}, {0, 13, 16},
+ {3, 14, 15}, {2, 13, 15}, {1, 12, 15}, {0, 12, 15}, {3, 13, 15}, {2, 12, 15}, {1, 11, 15}, {0, 11, 15},
+ {3, 12, 14}, {2, 11, 14}, {1, 10, 14}, {0, 10, 14}, {3, 11, 14}, {2, 10, 14}, {1, 9, 14}, {0, 9, 14},
+ {0, 8, 13}, {2, 9, 13}, {1, 8, 13}, {0, 7, 13}, {3, 10, 13}, {2, 8, 13}, {1, 7, 13}, {0, 6, 13},
+ {3, 9, 11}, {2, 7, 11}, {1, 6, 11}, {0, 5, 11}, {3, 8, 10},
+ {2, 6, 10}, {1, 5, 10}, {0, 4, 10}, {3, 7, 9}, {2, 5, 9}, {1, 4, 9}, {0, 3, 9}, {3, 6, 8},
+ {2, 4, 8}, {1, 3, 8}, {0, 2, 8}, {3, 5, 7}, {2, 3, 7}, {3, 4, 6}, {3, 4, 6}, {1, 2, 6},
+ {1, 2, 6}, {0, 1, 6}, {0, 1, 6}, {3, 3, 5}, {3, 3, 5}, {3, 3, 5}, {3, 3, 5}, {2, 2, 3},
+ {1, 1, 2}, {1, 1, 2}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}
+ };
+
+ const static uint8 TotCofNTrail2[84][3] = {{0, 0, 14 /* error */}, {0, 0, 14/*error */}, {3, 15, 13}, {3, 15, 13}, {3, 16, 14}, {2, 16, 14}, {1, 16, 14}, {0, 16, 14},
+ {1, 15, 14}, {0, 15, 14}, {2, 15, 14}, {1, 14, 14}, {2, 14, 13}, {2, 14, 13}, {0, 14, 13}, {0, 14, 13},
+ {3, 14, 13}, {2, 13, 13}, {1, 13, 13}, {0, 13, 13}, {3, 13, 13}, {2, 12, 13}, {1, 12, 13}, {0, 12, 13},
+ {0, 11, 12}, {2, 11, 12}, {1, 11, 12}, {0, 10, 12}, {3, 12, 12}, {2, 10, 12}, {1, 10, 12}, {0, 9, 12},
+ {3, 11, 11}, {2, 9, 11}, {1, 9, 11}, {0, 8, 11}, {3, 10, 11}, {2, 8, 11}, {1, 8, 11}, {0, 7, 11},
+ {3, 9, 9}, {2, 7, 9}, {1, 7, 9}, {0, 6, 9}, {0, 5, 8}, {0, 5, 8}, {2, 6, 8}, {2, 6, 8},
+ {1, 6, 8}, {1, 6, 8}, {0, 4, 8}, {0, 4, 8}, {3, 8, 7}, {2, 5, 7}, {1, 5, 7}, {0, 3, 7},
+ {3, 7, 6}, {3, 7, 6}, {2, 4, 6}, {2, 4, 6}, {1, 4, 6}, {1, 4, 6}, {0, 2, 6}, {0, 2, 6},
+ {3, 6, 6}, {2, 3, 6}, {1, 3, 6}, {0, 1, 6}, {3, 5, 5}, {3, 5, 5}, {1, 2, 5}, {1, 2, 5},
+ {3, 4, 4}, {3, 3, 4}, {2, 2, 3}, {2, 2, 3}, {1, 1, 2}, {1, 1, 2}, {1, 1, 2}, {1, 1, 2},
+ {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}
+ };
+
+ const static uint8 TotCofNTrail3[64][3] = {{0, 0, 10/*error*/}, {0, 16, 10}, {3, 16, 10}, {2, 16, 10}, {1, 16, 10}, {0, 15, 10}, {3, 15, 10},
+ {2, 15, 10}, {1, 15, 10}, {0, 14, 10}, {3, 14, 10}, {2, 14, 10}, {1, 14, 10}, {0, 13, 10}, {1, 13, 9},
+ {1, 13, 9}, {0, 12, 9}, {2, 13, 9}, {1, 12, 9}, {0, 11, 9}, {3, 13, 9}, {2, 12, 9}, {1, 11, 9},
+ {0, 10, 9}, {3, 12, 8}, {2, 11, 8}, {1, 10, 8}, {0, 9, 8}, {3, 11, 8}, {2, 10, 8}, {1, 9, 8},
+ {0, 8, 8}, {0, 7, 7}, {0, 6, 7}, {2, 9, 7}, {0, 5, 7}, {3, 10, 7}, {2, 8, 7}, {1, 8, 7},
+ {0, 4, 7}, {0, 3, 6}, {2, 7, 6}, {1, 7, 6}, {0, 2, 6}, {3, 9, 6}, {2, 6, 6}, {1, 6, 6},
+ {0, 1, 6}, {1, 5, 5}, {2, 5, 5}, {1, 4, 5}, {2, 4, 5}, {1, 3, 5}, {3, 8, 5}, {2, 3, 5},
+ {1, 2, 5}, {3, 7, 4}, {3, 6, 4}, {3, 5, 4}, {3, 4, 4}, {3, 3, 4}, {2, 2, 4}, {1, 1, 4},
+ {0, 0, 4}
+ };
+#endif
+ uint code;
+
+#ifdef PV_NO_CLZ
+ uint8 *pcode;
+ if (nC < 2)
+ {
+ BitstreamShowBits(stream, 16, &code);
+
+ if (code >= 8192)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>13)+65+2][0]);
+ }
+ else if (code >= 2048)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>9)+50+2][0]);
+ }
+ else if (code >= 1024)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>8)+46+2][0]);
+ }
+ else if (code >= 512)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>7)+42+2][0]);
+ }
+ else if (code >= 256)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>6)+38+2][0]);
+ }
+ else if (code >= 128)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>5)+34+2][0]);
+ }
+ else if (code >= 64)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>3)+22+2][0]);
+ }
+ else if (code >= 32)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>2)+14+2][0]);
+ }
+ else if (code >= 16)
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code>>1)+6+2][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotCofNTrail1[(code-2)+2][0]);
+ }
+
+ *TrailingOnes = pcode[0];
+ *TotalCoeff = pcode[1];
+
+ BitstreamFlushBits(stream, pcode[2]);
+ }
+ else if (nC < 4)
+ {
+ BitstreamShowBits(stream, 14, &code);
+
+ if (code >= 4096)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>10)+66+2][0]);
+ }
+ else if (code >= 2048)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>8)+54+2][0]);
+ }
+ else if (code >= 512)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>7)+46+2][0]);
+ }
+ else if (code >= 128)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>5)+34+2][0]);
+ }
+ else if (code >= 64)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>3)+22+2][0]);
+ }
+ else if (code >= 32)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>2)+14+2][0]);
+ }
+ else if (code >= 16)
+ {
+ pcode = (uint8*) & (TotCofNTrail2[(code>>1)+6+2][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotCofNTrail2[code-2+2][0]);
+ }
+ *TrailingOnes = pcode[0];
+ *TotalCoeff = pcode[1];
+
+ BitstreamFlushBits(stream, pcode[2]);
+ }
+ else if (nC < 8)
+ {
+ BitstreamShowBits(stream, 10, &code);
+
+ if (code >= 512)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>6)+47+1][0]);
+ }
+ else if (code >= 256)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>5)+39+1][0]);
+ }
+ else if (code >= 128)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>4)+31+1][0]);
+ }
+ else if (code >= 64)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>3)+23+1][0]);
+ }
+ else if (code >= 32)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>2)+15+1][0]);
+ }
+ else if (code >= 16)
+ {
+ pcode = (uint8*) & (TotCofNTrail3[(code>>1)+7+1][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotCofNTrail3[code-1+1][0]);
+ }
+ *TrailingOnes = pcode[0];
+ *TotalCoeff = pcode[1];
+
+ BitstreamFlushBits(stream, pcode[2]);
+ }
+ else
+ {
+ /* read 6 bit FLC */
+ BitstreamReadBits(stream, 6, &code);
+
+
+ *TrailingOnes = code & 3;
+ *TotalCoeff = (code >> 2) + 1;
+
+ if (*TotalCoeff > 16)
+ {
+ *TotalCoeff = 16; // _ERROR
+ }
+
+ if (code == 3)
+ {
+ *TrailingOnes = 0;
+ (*TotalCoeff)--;
+ }
+ }
+#else
+ const VLCNumCoeffTrail *ptr;
+ const ShiftOffset *ptr_indx;
+ uint temp, leading_zeros = 0;
+
+ if (nC < 8)
+ {
+
+ BitstreamShowBits(stream, 16, &code);
+ temp = code | 1;
+
+ PV_CLZ(leading_zeros, temp)
+
+ temp = nC_table[nC];
+ ptr_indx = &NumCoeffTrailOnes_indx[temp][leading_zeros];
+ ptr = &NumCoeffTrailOnes[temp][(code >> ptr_indx->shift) + ptr_indx->offset];
+ *TrailingOnes = ptr->trailing;
+ *TotalCoeff = ptr->total_coeff;
+ BitstreamFlushBits(stream, ptr->length);
+ }
+ else
+ {
+ /* read 6 bit FLC */
+ BitstreamReadBits(stream, 6, &code);
+
+
+ *TrailingOnes = code & 3;
+ *TotalCoeff = (code >> 2) + 1;
+
+ if (*TotalCoeff > 16)
+ {
+ *TotalCoeff = 16; // _ERROR
+ }
+
+ if (code == 3)
+ {
+ *TrailingOnes = 0;
+ (*TotalCoeff)--;
+ }
+ }
+#endif
+ return AVCDEC_SUCCESS;
+}
+
+/* TO BE OPTIMIZED !!!!! */
+AVCDec_Status ce_TotalCoeffTrailingOnesChromaDC(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff)
+{
+ AVCDec_Status status;
+
+ const static uint8 TotCofNTrail5[21][3] =
+ {
+ {3, 4, 7}, {3, 4, 7}, {2, 4, 8}, {1, 4, 8}, {2, 3, 7}, {2, 3, 7}, {1, 3, 7},
+ {1, 3, 7}, {0, 4, 6}, {0, 3, 6}, {0, 2, 6}, {3, 3, 6}, {1, 2, 6}, {0, 1, 6},
+ {2, 2, 3}, {0, 0, 2}, {0, 0, 2}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}
+ };
+
+ uint code;
+ uint8 *pcode;
+
+ status = BitstreamShowBits(stream, 8, &code);
+
+ if (code >= 32)
+ {
+ pcode = (uint8*) & (TotCofNTrail5[(code>>5)+13][0]);
+ }
+ else if (code >= 8)
+ {
+ pcode = (uint8*) & (TotCofNTrail5[(code>>2)+6][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotCofNTrail5[code][0]);
+ }
+
+ *TrailingOnes = pcode[0];
+ *TotalCoeff = pcode[1];
+
+ BitstreamFlushBits(stream, pcode[2]);
+
+ return status;
+}
+
+/* see Table 9-6 */
+AVCDec_Status ce_LevelPrefix(AVCDecBitstream *stream, uint *code)
+{
+ uint temp;
+ uint leading_zeros = 0;
+ BitstreamShowBits(stream, 16, &temp);
+ temp |= 1 ;
+
+ PV_CLZ(leading_zeros, temp)
+
+ BitstreamFlushBits(stream, leading_zeros + 1);
+ *code = leading_zeros;
+ return AVCDEC_SUCCESS;
+}
+
+/* see Table 9-7 and 9-8 */
+AVCDec_Status ce_TotalZeros(AVCDecBitstream *stream, int *code, int TotalCoeff)
+{
+ const static uint8 TotZero1[28][2] = {{15, 9}, {14, 9}, {13, 9}, {12, 8},
+ {12, 8}, {11, 8}, {11, 8}, {10, 7}, {9, 7}, {8, 6}, {8, 6}, {7, 6}, {7, 6}, {6, 5}, {6, 5},
+ {6, 5}, {6, 5}, {5, 5}, {5, 5}, {5, 5}, {5, 5}, {4, 4}, {3, 4},
+ {2, 3}, {2, 3}, {1, 3}, {1, 3}, {0, 1}
+ };
+
+ const static uint8 TotZero2n3[2][18][2] = {{{14, 6}, {13, 6}, {12, 6}, {11, 6},
+ {10, 5}, {10, 5}, {9, 5}, {9, 5}, {8, 4}, {7, 4}, {6, 4}, {5, 4}, {4, 3}, {4, 3},
+ {3, 3}, {2, 3}, {1, 3}, {0, 3}},
+
+ /*const static uint8 TotZero3[18][2]=*/{{13, 6}, {11, 6}, {12, 5}, {12, 5}, {10, 5},
+ {10, 5}, {9, 5}, {9, 5}, {8, 4}, {5, 4}, {4, 4}, {0, 4}, {7, 3}, {7, 3}, {6, 3}, {3, 3},
+ {2, 3}, {1, 3}}
+ };
+
+ const static uint8 TotZero4[17][2] = {{12, 5}, {11, 5}, {10, 5}, {0, 5}, {9, 4},
+ {9, 4}, {7, 4}, {7, 4}, {3, 4}, {3, 4}, {2, 4}, {2, 4}, {8, 3}, {6, 3}, {5, 3}, {4, 3}, {1, 3}
+ };
+
+ const static uint8 TotZero5[13][2] = {{11, 5}, {9, 5}, {10, 4}, {8, 4}, {2, 4},
+ {1, 4}, {0, 4}, {7, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}
+ };
+
+ const static uint8 TotZero6to10[5][15][2] = {{{10, 6}, {0, 6}, {1, 5}, {1, 5}, {8, 4},
+ {8, 4}, {8, 4}, {8, 4}, {9, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}, {2, 3}},
+
+ /*const static uint8 TotZero7[15][2]=*/{{9, 6}, {0, 6}, {1, 5}, {1, 5}, {7, 4},
+ {7, 4}, {7, 4}, {7, 4}, {8, 3}, {6, 3}, {4, 3}, {3, 3}, {2, 3}, {5, 2}, {5, 2}},
+
+ /*const static uint8 TotZero8[15][2]=*/{{8, 6}, {0, 6}, {2, 5}, {2, 5}, {1, 4},
+ {1, 4}, {1, 4}, {1, 4}, {7, 3}, {6, 3}, {3, 3}, {5, 2}, {5, 2}, {4, 2}, {4, 2}},
+
+ /*const static uint8 TotZero9[15][2]=*/{{1, 6}, {0, 6}, {7, 5}, {7, 5}, {2, 4},
+ {2, 4}, {2, 4}, {2, 4}, {5, 3}, {6, 2}, {6, 2}, {4, 2}, {4, 2}, {3, 2}, {3, 2}},
+
+ /*const static uint8 TotZero10[11][2]=*/{{1, 5}, {0, 5}, {6, 4}, {6, 4}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {5, 2}, {4, 2}, {3, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}
+ };
+
+ const static uint8 TotZero11[7][2] = {{0, 4}, {1, 4}, {2, 3}, {2, 3}, {3, 3}, {5, 3}, {4, 1}};
+
+ const static uint8 TotZero12to15[4][5][2] =
+ {
+ {{3, 1}, {2, 2}, {4, 3}, {1, 4}, {0, 4}},
+ {{2, 1}, {3, 2}, {1, 3}, {0, 3}, {0, 0}},
+ {{2, 1}, {1, 2}, {0, 2}, {0, 0}, {0, 0}},
+ {{1, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}}
+ };
+
+ uint temp, mask;
+ int indx;
+ uint8 *pcode;
+
+ if (TotalCoeff == 1)
+ {
+ BitstreamShowBits(stream, 9, &temp);
+
+ if (temp >= 256)
+ {
+ pcode = (uint8*) & (TotZero1[27][0]);
+ }
+ else if (temp >= 64)
+ {
+ pcode = (uint8*) & (TotZero1[(temp>>5)+19][0]);
+ }
+ else if (temp >= 8)
+ {
+ pcode = (uint8*) & (TotZero1[(temp>>2)+5][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero1[temp-1][0]);
+ }
+
+ }
+ else if (TotalCoeff == 2 || TotalCoeff == 3)
+ {
+ BitstreamShowBits(stream, 6, &temp);
+
+ if (temp >= 32)
+ {
+ pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][(temp>>3)+10][0]);
+ }
+ else if (temp >= 8)
+ {
+ pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][(temp>>2)+6][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][temp][0]);
+ }
+ }
+ else if (TotalCoeff == 4)
+ {
+ BitstreamShowBits(stream, 5, &temp);
+
+ if (temp >= 12)
+ {
+ pcode = (uint8*) & (TotZero4[(temp>>2)+9][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero4[temp][0]);
+ }
+ }
+ else if (TotalCoeff == 5)
+ {
+ BitstreamShowBits(stream, 5, &temp);
+
+ if (temp >= 16)
+ {
+ pcode = (uint8*) & (TotZero5[(temp>>2)+5][0]);
+ }
+ else if (temp >= 2)
+ {
+ pcode = (uint8*) & (TotZero5[(temp>>1)+1][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero5[temp][0]);
+ }
+ }
+ else if (TotalCoeff >= 6 && TotalCoeff <= 10)
+ {
+ if (TotalCoeff == 10)
+ {
+ BitstreamShowBits(stream, 5, &temp);
+ }
+ else
+ {
+ BitstreamShowBits(stream, 6, &temp);
+ }
+
+
+ if (temp >= 8)
+ {
+ pcode = (uint8*) & (TotZero6to10[TotalCoeff-6][(temp>>3)+7][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero6to10[TotalCoeff-6][temp][0]);
+ }
+ }
+ else if (TotalCoeff == 11)
+ {
+ BitstreamShowBits(stream, 4, &temp);
+
+
+ if (temp >= 8)
+ {
+ pcode = (uint8*) & (TotZero11[6][0]);
+ }
+ else if (temp >= 4)
+ {
+ pcode = (uint8*) & (TotZero11[(temp>>1)+2][0]);
+ }
+ else
+ {
+ pcode = (uint8*) & (TotZero11[temp][0]);
+ }
+ }
+ else
+ {
+ BitstreamShowBits(stream, (16 - TotalCoeff), &temp);
+ mask = 1 << (15 - TotalCoeff);
+ indx = 0;
+ while ((temp&mask) == 0 && indx < (16 - TotalCoeff)) /* search location of 1 bit */
+ {
+ mask >>= 1;
+ indx++;
+ }
+
+ pcode = (uint8*) & (TotZero12to15[TotalCoeff-12][indx]);
+ }
+
+ *code = pcode[0];
+ BitstreamFlushBits(stream, pcode[1]);
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see Table 9-9 */
+AVCDec_Status ce_TotalZerosChromaDC(AVCDecBitstream *stream, int *code, int TotalCoeff)
+{
+ const static uint8 TotZeroChrom1to3[3][8][2] =
+ {
+ {{3, 3}, {2, 3}, {1, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
+ {{2, 2}, {2, 2}, {1, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
+ {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
+ };
+
+
+ uint temp;
+ uint8 *pcode;
+
+ BitstreamShowBits(stream, 3, &temp);
+ pcode = (uint8*) & (TotZeroChrom1to3[TotalCoeff-1][temp]);
+
+ *code = pcode[0];
+
+ BitstreamFlushBits(stream, pcode[1]);
+
+ return AVCDEC_SUCCESS;
+}
+
+/* see Table 9-10 */
+AVCDec_Status ce_RunBefore(AVCDecBitstream *stream, int *code, int zerosLeft)
+{
+ const static int codlen[6] = {1, 2, 2, 3, 3, 3}; /* num bits to read */
+ const static uint8 RunBeforeTab[6][8][2] = {{{1, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
+ /*const static int RunBefore2[4][2]=*/{{2, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
+ /*const static int RunBefore3[4][2]=*/{{3, 2}, {2, 2}, {1, 2}, {0, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
+ /*const static int RunBefore4[7][2]=*/{{4, 3}, {3, 3}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {0, 2}, {0, 2}},
+ /*const static int RunBefore5[7][2]=*/{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 2}, {1, 2}, {0, 2}, {0, 2}},
+ /*const static int RunBefore6[7][2]=*/{{1, 3}, {2, 3}, {4, 3}, {3, 3}, {6, 3}, {5, 3}, {0, 2}, {0, 2}}
+ };
+
+ uint temp;
+ uint8 *pcode;
+ int indx;
+
+ if (zerosLeft <= 6)
+ {
+ BitstreamShowBits(stream, codlen[zerosLeft-1], &temp);
+
+ pcode = (uint8*) & (RunBeforeTab[zerosLeft-1][temp][0]);
+
+ *code = pcode[0];
+
+ BitstreamFlushBits(stream, pcode[1]);
+ }
+ else
+ {
+ BitstreamReadBits(stream, 3, &temp);
+ if (temp)
+ {
+ *code = 7 - temp;
+ }
+ else
+ {
+ BitstreamShowBits(stream, 9, &temp);
+ temp <<= 7;
+ temp |= 1;
+ indx = 0;
+ PV_CLZ(indx, temp)
+ *code = 7 + indx;
+ BitstreamFlushBits(stream, indx + 1);
+ }
+ }
+
+
+ return AVCDEC_SUCCESS;
+}