summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--media/libstagefright/Android.mk6
-rw-r--r--media/libstagefright/OMXCodec.cpp4
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk4
-rw-r--r--media/libstagefright/codecs/amrnb/common/Android.mk4
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk4
-rw-r--r--media/libstagefright/codecs/amrwb/Android.mk4
-rw-r--r--media/libstagefright/codecs/avc/Android.mk4
-rw-r--r--media/libstagefright/codecs/avc/common/Android.mk21
-rw-r--r--media/libstagefright/codecs/avc/common/include/avc_types.h14
-rw-r--r--media/libstagefright/codecs/avc/common/include/avcapi_common.h274
-rw-r--r--media/libstagefright/codecs/avc/common/include/avcint_common.h882
-rw-r--r--media/libstagefright/codecs/avc/common/include/avclib_common.h555
-rw-r--r--media/libstagefright/codecs/avc/common/src/deblock.cpp1666
-rw-r--r--media/libstagefright/codecs/avc/common/src/dpb.cpp724
-rw-r--r--media/libstagefright/codecs/avc/common/src/fmo.cpp249
-rw-r--r--media/libstagefright/codecs/avc/common/src/mb_access.cpp471
-rw-r--r--media/libstagefright/codecs/avc/common/src/reflist.cpp596
-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
-rw-r--r--media/libstagefright/codecs/avc/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/mp3dec/Android.mk4
-rw-r--r--media/libstagefright/include/AVCDecoder.h86
38 files changed, 16372 insertions, 18 deletions
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 83d492c..d4c6708 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -56,10 +56,14 @@ ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
LOCAL_STATIC_LIBRARIES := \
libstagefright_aacdec \
libstagefright_amrnbdec \
- libstagefright_amrnb_common \
libstagefright_amrwbdec \
+ libstagefright_avcdec \
libstagefright_mp3dec
+LOCAL_SHARED_LIBRARIES += \
+ libstagefright_amrnb_common \
+ libstagefright_avc_common
+
endif
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 093e2e0..fc3c05b 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -22,6 +22,7 @@
#include "include/AACDecoder.h"
#include "include/AMRNBDecoder.h"
#include "include/AMRWBDecoder.h"
+#include "include/AVCDecoder.h"
#include "include/MP3Decoder.h"
#endif
@@ -300,6 +301,9 @@ sp<MediaSource> OMXCodec::Create(
return new AMRWBDecoder(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
return new MP3Decoder(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
+ && (flags & kPreferSoftwareCodecs)) {
+ return new AVCDecoder(source);
}
#endif
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 7f06095..d5d8f3e 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -149,10 +149,6 @@ LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL
LOCAL_C_INCLUDES := frameworks/base/media/libstagefright/include
-LOCAL_SHARED_LIBRARIES := \
- libstagefright \
- libutils
-
LOCAL_MODULE := libstagefright_aacdec
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk
index b22be77..2657a52 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.mk
+++ b/media/libstagefright/codecs/amrnb/common/Android.mk
@@ -69,6 +69,8 @@ LOCAL_C_INCLUDES := \
LOCAL_CFLAGS := \
-DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF=
+LOCAL_PRELINK_MODULE:= false
+
LOCAL_MODULE := libstagefright_amrnb_common
-include $(BUILD_STATIC_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 0852ff3..a545762 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -49,10 +49,6 @@ LOCAL_C_INCLUDES := \
LOCAL_CFLAGS := \
-DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
-LOCAL_SHARED_LIBRARIES := \
- libstagefright \
- libutils
-
LOCAL_MODULE := libstagefright_amrnbdec
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index 1c80f08..ab591d7 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -51,10 +51,6 @@ LOCAL_C_INCLUDES := \
LOCAL_CFLAGS := \
-DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
-LOCAL_SHARED_LIBRARIES := \
- libstagefright \
- libutils
-
LOCAL_MODULE := libstagefright_amrwbdec
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/Android.mk b/media/libstagefright/codecs/avc/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/avc/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/codecs/avc/common/Android.mk b/media/libstagefright/codecs/avc/common/Android.mk
new file mode 100644
index 0000000..39c6da8
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/deblock.cpp \
+ src/dpb.cpp \
+ src/fmo.cpp \
+ src/mb_access.cpp \
+ src/reflist.cpp
+
+LOCAL_MODULE := libstagefright_avc_common
+
+LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include
+
+LOCAL_PRELINK_MODULE:= false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/common/include/avc_types.h b/media/libstagefright/codecs/avc/common/include/avc_types.h
new file mode 100644
index 0000000..73cad89
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avc_types.h
@@ -0,0 +1,14 @@
+#ifndef AVC_TYPES_H_
+
+#define AVC_TYPES_H_
+
+#include <stdint.h>
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef unsigned int uint;
+
+#endif // AVC_TYPES_H_
diff --git a/media/libstagefright/codecs/avc/common/include/avcapi_common.h b/media/libstagefright/codecs/avc/common/include/avcapi_common.h
new file mode 100644
index 0000000..3331689
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avcapi_common.h
@@ -0,0 +1,274 @@
+/* ------------------------------------------------------------------
+ * 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 common type definitions and enumerations used by AVC encoder
+and decoder libraries which are exposed to the users.
+@publishedAll
+*/
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#define AVCAPI_COMMON_H_INCLUDED
+
+#include "avc_types.h"
+
+#define PV_MEMORY_POOL
+/**
+This is common return status.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_NO_BUFFER = -2,
+ AVC_MEMORY_FAIL = -1,
+ AVC_FAIL = 0,
+ AVC_SUCCESS = 1,
+ AVC_PICTURE_OUTPUT_READY = 2
+} AVCStatus;
+
+/**
+This enumeration is for profiles. The value follows the profile_idc in sequence
+parameter set rbsp. See Annex A.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_BASELINE = 66,
+ AVC_MAIN = 77,
+ AVC_EXTENDED = 88,
+ AVC_HIGH = 100,
+ AVC_HIGH10 = 110,
+ AVC_HIGH422 = 122,
+ AVC_HIGH444 = 144
+} AVCProfile;
+
+/**
+This enumeration is for levels. The value follows the level_idc in sequence
+parameter set rbsp. See Annex A.
+@published All
+*/
+typedef enum
+{
+ AVC_LEVEL_AUTO = 0,
+ AVC_LEVEL1_B = 9,
+ AVC_LEVEL1 = 10,
+ AVC_LEVEL1_1 = 11,
+ AVC_LEVEL1_2 = 12,
+ AVC_LEVEL1_3 = 13,
+ AVC_LEVEL2 = 20,
+ AVC_LEVEL2_1 = 21,
+ AVC_LEVEL2_2 = 22,
+ AVC_LEVEL3 = 30,
+ AVC_LEVEL3_1 = 31,
+ AVC_LEVEL3_2 = 32,
+ AVC_LEVEL4 = 40,
+ AVC_LEVEL4_1 = 41,
+ AVC_LEVEL4_2 = 42,
+ AVC_LEVEL5 = 50,
+ AVC_LEVEL5_1 = 51
+} AVCLevel;
+
+/**
+This enumeration follows Table 7-1 for NAL unit type codes.
+This may go to avccommon_api.h later (external common).
+@publishedAll
+*/
+typedef enum
+{
+ AVC_NALTYPE_SLICE = 1, /* non-IDR non-data partition */
+ AVC_NALTYPE_DPA = 2, /* data partition A */
+ AVC_NALTYPE_DPB = 3, /* data partition B */
+ AVC_NALTYPE_DPC = 4, /* data partition C */
+ AVC_NALTYPE_IDR = 5, /* IDR NAL */
+ AVC_NALTYPE_SEI = 6, /* supplemental enhancement info */
+ AVC_NALTYPE_SPS = 7, /* sequence parameter set */
+ AVC_NALTYPE_PPS = 8, /* picture parameter set */
+ AVC_NALTYPE_AUD = 9, /* access unit delimiter */
+ AVC_NALTYPE_EOSEQ = 10, /* end of sequence */
+ AVC_NALTYPE_EOSTREAM = 11, /* end of stream */
+ AVC_NALTYPE_FILL = 12 /* filler data */
+} AVCNalUnitType;
+
+/**
+This enumeration specifies debug logging type.
+This may go to avccommon_api.h later (external common).
+@publishedAll
+*/
+typedef enum
+{
+ AVC_LOGTYPE_ERROR = 0,
+ AVC_LOGTYPE_WARNING = 1,
+ AVC_LOGTYPE_INFO = 2
+} AVCLogType;
+
+/**
+This enumerate the status of certain flags.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_OFF = 0,
+ AVC_ON = 1
+} AVCFlag;
+
+/**
+This structure contains input information.
+Note, this structure is identical to AVCDecOutput for now.
+*/
+typedef struct tagAVCFrameIO
+{
+ /** A unique identification number for a particular instance of this structure.
+ To remain unchanged by the application between the time when it is given to the
+ library and the time when the library returns it back. */
+ uint32 id;
+
+ /** Array of pointers to Y,Cb,Cr content in 4:2:0 format. For AVC decoding,
+ this memory is allocated by the AVC decoder library. For AVC encoding, only the
+ memory for original unencoded frame is allocated by the application. Internal
+ memory is also allocated by the AVC encoder library. */
+ uint8 *YCbCr[3];
+
+ /** In/Out: Coded width of the luma component, it has to be multiple of 16. */
+ int pitch;
+
+ /** In/Out: Coded height of the luma component, must be multiple of 16. */
+ int height;
+
+ /** In/Out: Display width, less than picth */
+ int clip_width;
+
+ /** In/Out: Display height, less than height */
+ int clip_height;
+
+ /** Input: Origin of the display area [0]=>row, [1]=>column */
+ int clip_origin[2];
+
+ /** Output: Frame number in de/encoding order (not necessary)*/
+ uint32 coding_order;
+
+ /** Output: Frame number in displaying order (this may or may not be associated with the POC at all!!!). */
+ uint32 disp_order;
+
+ /** In/Out: Flag for use for reference or not. */
+ uint is_reference;
+
+ /** In/Out: Coding timestamp in msec (not display timestamp) */
+ uint32 coding_timestamp;
+
+ /* there could be something else here such as format, DON (decoding order number)
+ if available thru SEI, etc. */
+} AVCFrameIO;
+
+
+/** CALLBACK FUNCTION TO BE IMPLEMENTED BY APPLICATION */
+/** In AVCDecControls structure, userData is a pointer to an object with the following
+ member functions.
+*/
+
+
+/** @brief Decoded picture buffers (DPB) must be allocated or re-allocated before an
+ IDR frame is decoded. If PV_MEMORY_POOL is not defined, AVC lib will allocate DPB
+ internally which cannot be shared with the application. In that case, this function
+ will not be called.
+ @param userData The same value of userData in AVCHandle object.
+ @param frame_size_in_mbs The size of each frame in number of macroblocks.
+ @param num_frames The number of frames in DPB.
+ @return 1 for success, 0 for fail (cannot allocate DPB)
+*/
+
+typedef int (*FunctionType_DPBAlloc)(void *userData, uint frame_size_in_mbs, uint num_buffers);
+
+/** @brief AVC library calls this function is reserve a memory of one frame from the DPB.
+ Once reserved, this frame shall not be deleted or over-written by the app.
+ @param userData The same value of userData in AVCHandle object.
+ @param indx Index of a frame in DPB (AVC library keeps track of the index).
+ @param yuv The address of the yuv pointer returned to the AVC lib.
+ @return 1 for success, 0 for fail (no frames available to bind).
+ */
+typedef int (*FunctionType_FrameBind)(void *userData, int indx, uint8 **yuv);
+
+/** @brief AVC library calls this function once a bound frame is not needed for decoding
+ operation (falls out of the sliding window, or marked unused for reference).
+ @param userData The same value of userData in AVCHandle object.
+ @param indx Index of frame to be unbound (AVC library keeps track of the index).
+ @return none.
+*/
+typedef void (*FuctionType_FrameUnbind)(void *userData, int);
+
+/** Pointer to malloc function for general memory allocation, so that application can keep track of
+ memory usage.
+\param "size" "Size of requested memory in bytes."
+\param "attribute" "Some value specifying types, priority, etc. of the memory."
+\return "The address of the allocated memory casted to int"
+*/
+typedef int (*FunctionType_Malloc)(void *userData, int32 size, int attribute);
+
+/** Function pointer to free
+\param "mem" "Pointer to the memory to be freed casted to int"
+\return "void"
+*/
+typedef void (*FunctionType_Free)(void *userData, int mem);
+
+/** Debug logging information is returned to the application thru this function.
+\param "type" "Type of logging message, see definition of AVCLogType."
+\param "string1" "Logging message."
+\param "string2" "To be defined."
+*/
+typedef void (*FunctionType_DebugLog)(uint32 *userData, AVCLogType type, char *string1, int val1, int val2);
+
+/**
+This structure has to be allocated and maintained by the user of the library.
+This structure is used as a handle to the library object.
+*/
+typedef struct tagAVCHandle
+{
+ /** A pointer to the internal data structure. Users have to make sure that this value
+ is NULL at the beginning.
+ */
+ void *AVCObject;
+
+ /** A pointer to user object which has the following member functions used for
+ callback purpose. !!! */
+ void *userData;
+
+ /** Pointers to functions implemented by the users of AVC library */
+ FunctionType_DPBAlloc CBAVC_DPBAlloc;
+
+ FunctionType_FrameBind CBAVC_FrameBind;
+
+ FuctionType_FrameUnbind CBAVC_FrameUnbind;
+
+ FunctionType_Malloc CBAVC_Malloc;
+
+ FunctionType_Free CBAVC_Free;
+
+ FunctionType_DebugLog CBAVC_DebugLog;
+
+ /** Flag to enable debugging */
+ uint32 debugEnable;
+
+} AVCHandle;
+
+
+
+#ifdef PVDEBUGMSG_LOG
+#define DEBUG_LOG(a,b,c,d,e) CBAVC_DebugLog(a,b,c,d,e)
+#else
+#define DEBUG_LOG(a,b,c,d,e)
+#endif
+
+#endif /* _AVCAPI_COMMON_H_ */
diff --git a/media/libstagefright/codecs/avc/common/include/avcint_common.h b/media/libstagefright/codecs/avc/common/include/avcint_common.h
new file mode 100644
index 0000000..465e604
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avcint_common.h
@@ -0,0 +1,882 @@
+/* ------------------------------------------------------------------
+ * 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 common code shared between AVC decoder and AVC encoder for
+internal use only.
+@publishedAll
+*/
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#define AVCINT_COMMON_H_INCLUDED
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#include "avcapi_common.h"
+#endif
+
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+
+
+/**
+Mathematic functions defined in subclause 5.7.
+Can be replaced with assembly instructions for speedup.
+@publishedAll
+*/
+#define AVC_ABS(x) (((x)<0)? -(x) : (x))
+#define AVC_SIGN(x) (((x)<0)? -1 : 1)
+#define AVC_SIGN0(x) (((x)<0)? -1 : (((x)>0) ? 1 : 0))
+#define AVC_MAX(x,y) ((x)>(y)? (x):(y))
+#define AVC_MIN(x,y) ((x)<(y)? (x):(y))
+#define AVC_MEDIAN(A,B,C) ((A) > (B) ? ((A) < (C) ? (A) : (B) > (C) ? (B) : (C)): (B) < (C) ? (B) : (C) > (A) ? (C) : (A))
+#define AVC_CLIP3(a,b,x) (AVC_MAX(a,AVC_MIN(x,b))) /* clip x between a and b */
+#define AVC_CLIP(x) AVC_CLIP3(0,255,x)
+#define AVC_FLOOR(x) ((int)(x))
+#define AVC_RASTER_SCAN(x,y,n) ((x)+(y)*(n))
+#define AVC_ROUND(x) (AVC_SIGN(x)*AVC_FLOOR(AVC_ABS(x)+0.5))
+#define AVC_INVERSE_RASTER_SCAN(a,b,c,d,e) (((e)==0)? (((a)%((d)/(b)))*(b)): (((a)/((d)/(b)))*(c)))
+/* a:block address, b:block width, c:block height, d:total_width, e:x or y coordinate */
+
+#define DEFAULT_ATTR 0 /* default memory attribute */
+#define FAST_MEM_ATTR 1 /* fast memory attribute */
+
+
+/* This section is for definition of constants. */
+#define MB_SIZE 16
+#define BLOCK_SIZE 4
+#define EMULATION_PREVENTION_THREE_BYTE 0x3
+#define NUM_PIXELS_IN_MB (24*16)
+#define NUM_BLKS_IN_MB 24
+
+#define AVCNumI4PredMode 9
+#define AVCNumI16PredMode 4
+#define AVCNumIChromaMode 4
+
+/* constants used in the structures below */
+#define MAXIMUMVALUEOFcpb_cnt 32 /* used in HRDParams */
+#define MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 255 /* used in SeqParamSet */
+#define MAX_NUM_SLICE_GROUP 8 /* used in PicParamSet */
+#define MAX_REF_PIC_LIST_REORDERING 32 /* 32 is maximum according to Annex A, SliceHeader */
+#define MAX_DEC_REF_PIC_MARKING 64 /* 64 is the maximum possible given the max num ref pictures to 31. */
+#define MAX_FS (16+1) /* pre-defined size of frame store array */
+#define MAX_LEVEL_IDX 15 /* only 15 levels defined for now */
+#define MAX_REF_PIC_LIST 33 /* max size of the RefPicList0 and RefPicList1 */
+
+
+/**
+Architectural related macros.
+@publishedAll
+*/
+#ifdef USE_PRED_BLOCK
+#define MB_BASED_DEBLOCK
+#endif
+
+/**
+Picture type, PV created.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_FRAME = 3
+} AVCPictureType;
+
+/**
+This slice type follows Table 7-3. The bottom 5 items may not needed.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_P_SLICE = 0,
+ AVC_B_SLICE = 1,
+ AVC_I_SLICE = 2,
+ AVC_SP_SLICE = 3,
+ AVC_SI_SLICE = 4,
+ AVC_P_ALL_SLICE = 5,
+ AVC_B_ALL_SLICE = 6,
+ AVC_I_ALL_SLICE = 7,
+ AVC_SP_ALL_SLICE = 8,
+ AVC_SI_ALL_SLICE = 9
+} AVCSliceType;
+
+/**
+Types of the macroblock and partition. PV Created.
+@publishedAll
+*/
+typedef enum
+{
+ /* intra */
+ AVC_I4,
+ AVC_I16,
+ AVC_I_PCM,
+ AVC_SI4,
+
+ /* inter for both P and B*/
+ AVC_BDirect16,
+ AVC_P16,
+ AVC_P16x8,
+ AVC_P8x16,
+ AVC_P8,
+ AVC_P8ref0,
+ AVC_SKIP
+} AVCMBMode;
+
+/**
+Enumeration for sub-macroblock mode, interpreted from sub_mb_type.
+@publishedAll
+*/
+typedef enum
+{
+ /* for sub-partition mode */
+ AVC_BDirect8,
+ AVC_8x8,
+ AVC_8x4,
+ AVC_4x8,
+ AVC_4x4
+} AVCSubMBMode;
+
+/**
+Mode of prediction of partition or sub-partition. PV Created.
+Do not change the order!!! Used in table look-up mode prediction in
+vlc.c.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_Pred_L0 = 0,
+ AVC_Pred_L1,
+ AVC_BiPred,
+ AVC_Direct
+} AVCPredMode;
+
+
+/**
+Mode of intra 4x4 prediction. Table 8-2
+@publishedAll
+*/
+typedef enum
+{
+ AVC_I4_Vertical = 0,
+ AVC_I4_Horizontal,
+ AVC_I4_DC,
+ AVC_I4_Diagonal_Down_Left,
+ AVC_I4_Diagonal_Down_Right,
+ AVC_I4_Vertical_Right,
+ AVC_I4_Horizontal_Down,
+ AVC_I4_Vertical_Left,
+ AVC_I4_Horizontal_Up
+} AVCIntra4x4PredMode;
+
+/**
+Mode of intra 16x16 prediction. Table 8-3
+@publishedAll
+*/
+typedef enum
+{
+ AVC_I16_Vertical = 0,
+ AVC_I16_Horizontal,
+ AVC_I16_DC,
+ AVC_I16_Plane
+} AVCIntra16x16PredMode;
+
+
+/**
+Mode of intra chroma prediction. Table 8-4
+@publishedAll
+*/
+typedef enum
+{
+ AVC_IC_DC = 0,
+ AVC_IC_Horizontal,
+ AVC_IC_Vertical,
+ AVC_IC_Plane
+} AVCIntraChromaPredMode;
+
+/**
+Type of residual going to residual_block_cavlc function, PV created.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_Luma,
+ AVC_Intra16DC,
+ AVC_Intra16AC,
+ AVC_ChromaDC,
+ AVC_ChromaAC
+} AVCResidualType;
+
+
+/**
+This structure contains VUI parameters as specified in Annex E.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagHRDParams
+{
+ uint cpb_cnt_minus1; /* ue(v), range 0..31 */
+ uint bit_rate_scale; /* u(4) */
+ uint cpb_size_scale; /* u(4) */
+ uint32 bit_rate_value_minus1[MAXIMUMVALUEOFcpb_cnt];/* ue(v), range 0..2^32-2 */
+ uint32 cpb_size_value_minus1[MAXIMUMVALUEOFcpb_cnt]; /* ue(v), range 0..2^32-2 */
+ uint cbr_flag[MAXIMUMVALUEOFcpb_cnt]; /* u(1) */
+ uint initial_cpb_removal_delay_length_minus1; /* u(5), default 23 */
+ uint cpb_removal_delay_length_minus1; /* u(5), default 23 */
+ uint dpb_output_delay_length_minus1; /* u(5), default 23 */
+ uint time_offset_length; /* u(5), default 24 */
+} AVCHRDParams;
+
+/**
+This structure contains VUI parameters as specified in Annex E.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagVUIParam
+{
+ uint aspect_ratio_info_present_flag; /* u(1) */
+ uint aspect_ratio_idc; /* u(8), table E-1 */
+ uint sar_width; /* u(16) */
+ uint sar_height; /* u(16) */
+ uint overscan_info_present_flag; /* u(1) */
+ uint overscan_appropriate_flag; /* u(1) */
+ uint video_signal_type_present_flag; /* u(1) */
+ uint video_format; /* u(3), Table E-2, default 5, unspecified */
+ uint video_full_range_flag; /* u(1) */
+ uint colour_description_present_flag; /* u(1) */
+ uint colour_primaries; /* u(8), Table E-3, default 2, unspecified */
+ uint transfer_characteristics; /* u(8), Table E-4, default 2, unspecified */
+ uint matrix_coefficients; /* u(8), Table E-5, default 2, unspecified */
+ uint chroma_location_info_present_flag; /* u(1) */
+ uint chroma_sample_loc_type_top_field; /* ue(v), Fig. E-1range 0..5, default 0 */
+ uint chroma_sample_loc_type_bottom_field; /* ue(v) */
+ uint timing_info_present_flag; /* u(1) */
+ uint num_units_in_tick; /* u(32), must be > 0 */
+ uint time_scale; /* u(32), must be > 0 */
+ uint fixed_frame_rate_flag; /* u(1), Eq. C-13 */
+ uint nal_hrd_parameters_present_flag; /* u(1) */
+ AVCHRDParams nal_hrd_parameters; /* hrd_paramters */
+ uint vcl_hrd_parameters_present_flag; /* u(1) */
+ AVCHRDParams vcl_hrd_parameters; /* hrd_paramters */
+ /* if ((nal_hrd_parameters_present_flag || (vcl_hrd_parameters_present_flag)) */
+ uint low_delay_hrd_flag; /* u(1) */
+ uint pic_struct_present_flag;
+ uint bitstream_restriction_flag; /* u(1) */
+ uint motion_vectors_over_pic_boundaries_flag; /* u(1) */
+ uint max_bytes_per_pic_denom; /* ue(v), default 2 */
+ uint max_bits_per_mb_denom; /* ue(v), range 0..16, default 1 */
+ uint log2_max_mv_length_vertical; /* ue(v), range 0..16, default 16 */
+ uint log2_max_mv_length_horizontal; /* ue(v), range 0..16, default 16 */
+ uint max_dec_frame_reordering; /* ue(v) */
+ uint max_dec_frame_buffering; /* ue(v) */
+} AVCVUIParams;
+
+
+/**
+This structure contains information in a sequence parameter set NAL.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagSeqParamSet
+{
+ uint Valid; /* indicates the parameter set is valid */
+
+ uint profile_idc; /* u(8) */
+ uint constrained_set0_flag; /* u(1) */
+ uint constrained_set1_flag; /* u(1) */
+ uint constrained_set2_flag; /* u(1) */
+ uint constrained_set3_flag; /* u(1) */
+ uint level_idc; /* u(8) */
+ uint seq_parameter_set_id; /* ue(v), range 0..31 */
+ uint log2_max_frame_num_minus4; /* ue(v), range 0..12 */
+ uint pic_order_cnt_type; /* ue(v), range 0..2 */
+ /* if( pic_order_cnt_type == 0 ) */
+ uint log2_max_pic_order_cnt_lsb_minus4; /* ue(v), range 0..12 */
+ /* else if( pic_order_cnt_type == 1 ) */
+ uint delta_pic_order_always_zero_flag; /* u(1) */
+ int32 offset_for_non_ref_pic; /* se(v) */
+ int32 offset_for_top_to_bottom_field; /* se(v) */
+ uint num_ref_frames_in_pic_order_cnt_cycle; /* ue(v) , range 0..255 */
+ /* for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) */
+ int32 offset_for_ref_frame[MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE]; /* se(v) */
+ uint num_ref_frames; /* ue(v), range 0..16 */
+ uint gaps_in_frame_num_value_allowed_flag; /* u(1) */
+ uint pic_width_in_mbs_minus1; /* ue(v) */
+ uint pic_height_in_map_units_minus1; /* ue(v) */
+ uint frame_mbs_only_flag; /* u(1) */
+ /* if( !frame_mbs_only_flag ) */
+ uint mb_adaptive_frame_field_flag; /* u(1) */
+ uint direct_8x8_inference_flag; /* u(1), must be 1 when frame_mbs_only_flag is 0 */
+ uint frame_cropping_flag; /* u(1) */
+ /* if( frmae_cropping_flag) */
+ uint frame_crop_left_offset; /* ue(v) */
+ uint frame_crop_right_offset; /* ue(v) */
+ uint frame_crop_top_offset; /* ue(v) */
+ uint frame_crop_bottom_offset; /* ue(v) */
+ uint vui_parameters_present_flag; /* u(1) */
+// uint nal_hrd_parameters_present_flag;
+// uint vcl_hrd_parameters_present_flag;
+// AVCHRDParams *nal_hrd_parameters;
+// AVCHRDParams *vcl_hrd_parameters;
+ AVCVUIParams vui_parameters; /* AVCVUIParam */
+} AVCSeqParamSet;
+
+/**
+This structure contains information in a picture parameter set NAL.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagPicParamSet
+{
+ uint pic_parameter_set_id; /* ue(v), range 0..255 */
+ uint seq_parameter_set_id; /* ue(v), range 0..31 */
+ uint entropy_coding_mode_flag; /* u(1) */
+ uint pic_order_present_flag; /* u(1) */
+ uint num_slice_groups_minus1; /* ue(v), range in Annex A */
+ /* if( num_slice_groups_minus1 > 0) */
+ uint slice_group_map_type; /* ue(v), range 0..6 */
+ /* if( slice_group_map_type = = 0 ) */
+ /* for(0:1:num_slice_groups_minus1) */
+ uint run_length_minus1[MAX_NUM_SLICE_GROUP]; /* ue(v) */
+ /* else if( slice_group_map_type = = 2 ) */
+ /* for(0:1:num_slice_groups_minus1-1) */
+ uint top_left[MAX_NUM_SLICE_GROUP-1]; /* ue(v) */
+ uint bottom_right[MAX_NUM_SLICE_GROUP-1]; /* ue(v) */
+ /* else if( slice_group_map_type = = 3 || 4 || 5 */
+ uint slice_group_change_direction_flag; /* u(1) */
+ uint slice_group_change_rate_minus1; /* ue(v) */
+ /* else if( slice_group_map_type = = 6 ) */
+ uint pic_size_in_map_units_minus1; /* ue(v) */
+ /* for(0:1:pic_size_in_map_units_minus1) */
+ uint *slice_group_id; /* complete MBAmap u(v) */
+ uint num_ref_idx_l0_active_minus1; /* ue(v), range 0..31 */
+ uint num_ref_idx_l1_active_minus1; /* ue(v), range 0..31 */
+ uint weighted_pred_flag; /* u(1) */
+ uint weighted_bipred_idc; /* u(2), range 0..2 */
+ int pic_init_qp_minus26; /* se(v), range -26..25 */
+ int pic_init_qs_minus26; /* se(v), range -26..25 */
+ int chroma_qp_index_offset; /* se(v), range -12..12 */
+ uint deblocking_filter_control_present_flag; /* u(1) */
+ uint constrained_intra_pred_flag; /* u(1) */
+ uint redundant_pic_cnt_present_flag; /* u(1) */
+} AVCPicParamSet;
+
+
+/**
+This structure contains slice header information.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagSliceHeader
+{
+ uint first_mb_in_slice; /* ue(v) */
+ AVCSliceType slice_type; /* ue(v), Table 7-3, range 0..9 */
+ uint pic_parameter_set_id; /* ue(v), range 0..255 */
+ uint frame_num; /* u(v), see log2max_frame_num_minus4 */
+ /* if( !frame_mbs_only_flag) */
+ uint field_pic_flag; /* u(1) */
+ /* if(field_pic_flag) */
+ uint bottom_field_flag; /* u(1) */
+ /* if(nal_unit_type == 5) */
+ uint idr_pic_id; /* ue(v), range 0..65535 */
+ /* if(pic_order_cnt_type==0) */
+ uint pic_order_cnt_lsb; /* u(v), range 0..MaxPicOrderCntLsb-1 */
+ /* if(pic_order_present_flag && !field_pic_flag) */
+ int32 delta_pic_order_cnt_bottom; /* se(v) */
+ /* if(pic_order_cnt_type==1 && !delta_pic_order_always_zero_flag) */
+ /* if(pic_order_present_flag && !field_pic_flag) */
+ int32 delta_pic_order_cnt[2];
+ /* if(redundant_pic_cnt_present_flag) */
+ uint redundant_pic_cnt; /* ue(v), range 0..127 */
+ /* if(slice_type == B) */
+ uint direct_spatial_mv_pred_flag; /* u(1) */
+ /* if(slice_type == P || slice_type==SP || slice_type==B) */
+ uint num_ref_idx_active_override_flag; /* u(1) */
+ /* if(num_ref_idx_active_override_flag) */
+ uint num_ref_idx_l0_active_minus1; /* ue(v) */
+ /* if(slie_type == B) */
+ uint num_ref_idx_l1_active_minus1; /* ue(v) */
+
+ /* ref_pic_list_reordering() */
+ uint ref_pic_list_reordering_flag_l0; /* u(1) */
+ uint reordering_of_pic_nums_idc_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v), range 0..3 */
+ uint abs_diff_pic_num_minus1_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint long_term_pic_num_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint ref_pic_list_reordering_flag_l1; /* u(1) */
+ uint reordering_of_pic_nums_idc_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v), range 0..3 */
+ uint abs_diff_pic_num_minus1_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint long_term_pic_num_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+
+ /* end ref_pic_list_reordering() */
+ /* if(nal_ref_idc!=0) */
+ /* dec_ref_pic_marking() */
+ uint no_output_of_prior_pics_flag; /* u(1) */
+ uint long_term_reference_flag; /* u(1) */
+ uint adaptive_ref_pic_marking_mode_flag; /* u(1) */
+ uint memory_management_control_operation[MAX_DEC_REF_PIC_MARKING]; /* ue(v), range 0..6 */
+ uint difference_of_pic_nums_minus1[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint long_term_pic_num[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint long_term_frame_idx[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint max_long_term_frame_idx_plus1[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ /* end dec_ref_pic_marking() */
+ /* if(entropy_coding_mode_flag && slice_type!=I && slice_type!=SI) */
+ uint cabac_init_idc; /* ue(v), range 0..2 */
+ int slice_qp_delta; /* se(v), range 0..51 */
+ /* if(slice_type==SP || slice_type==SI) */
+ /* if(slice_type==SP) */
+ uint sp_for_switch_flag; /* u(1) */
+ int slice_qs_delta; /* se(v) */
+
+ /* if(deblocking_filter_control_present_flag)*/
+ uint disable_deblocking_filter_idc; /* ue(v), range 0..2 */
+ /* if(disable_deblocking_filter_idc!=1) */
+ int slice_alpha_c0_offset_div2; /* se(v), range -6..6, default 0 */
+ int slice_beta_offset_div_2; /* se(v), range -6..6, default 0 */
+ /* if(num_slice_groups_minus1>0 && slice_group_map_type>=3 && slice_group_map_type<=5)*/
+ uint slice_group_change_cycle; /* u(v), use ceil(log2(PicSizeInMapUnits/SliceGroupChangeRate + 1)) bits*/
+
+} AVCSliceHeader;
+
+/**
+This struct contains information about the neighboring pixel.
+@publishedAll
+*/
+typedef struct tagPixPos
+{
+ int available;
+ int mb_addr; /* macroblock address of the current pixel, see below */
+ int x; /* x,y positions of current pixel relative to the macroblock mb_addr */
+ int y;
+ int pos_x; /* x,y positions of current pixel relative to the picture. */
+ int pos_y;
+} AVCPixelPos;
+
+typedef struct tagNeighborAvailability
+{
+ int left;
+ int top; /* macroblock address of the current pixel, see below */
+ int top_right; /* x,y positions of current pixel relative to the macroblock mb_addr */
+} AVCNeighborAvailability;
+
+
+/**
+This structure contains picture data and related information necessary to be used as
+reference frame.
+@publishedAll
+*/
+typedef struct tagPictureData
+{
+ uint16 RefIdx; /* index used for reference frame */
+ uint8 *Sl; /* derived from base_dpb in AVCFrameStore */
+ uint8 *Scb; /* for complementary fields, YUV are interlaced */
+ uint8 *Scr; /* Sl of top_field and bottom_fields will be one line apart and the
+ stride will be 2 times the width. */
+ /* For non-complementary field, the above still applies. A special
+ output formatting is required. */
+
+ /* Then, necessary variables that need to be stored */
+ AVCPictureType picType; /* frame, top-field or bot-field */
+ /*bool*/
+ uint isReference;
+ /*bool*/
+ uint isLongTerm;
+ int PicOrderCnt;
+ int PicNum;
+ int LongTermPicNum;
+
+ int width; /* how many pixel per line */
+ int height;/* how many line */
+ int pitch; /* how many pixel between the line */
+
+ uint padded; /* flag for being padded */
+
+} AVCPictureData;
+
+/**
+This structure contains information for frame storage.
+@publishedAll
+*/
+typedef struct tagFrameStore
+{
+ uint8 *base_dpb; /* base pointer for the YCbCr */
+
+ int IsReference; /* 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used */
+ int IsLongTerm; /* 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used */
+ /* if IsLongTerm is true, IsReference can be ignored. */
+ /* if IsReference is true, IsLongterm will be checked for short-term or long-term. */
+ /* IsUsed must be true to enable the validity of IsReference and IsLongTerm */
+
+ int IsOutputted; /* has it been outputted via AVCDecGetOutput API, then don't output it again,
+ wait until it is returned. */
+ AVCPictureData frame;
+
+ int FrameNum;
+ int FrameNumWrap;
+ int LongTermFrameIdx;
+ int PicOrderCnt; /* of the frame, smaller of the 2 fields */
+
+} AVCFrameStore;
+
+/**
+This structure maintains the actual memory for the decoded picture buffer (DPB) which is
+allocated at the beginning according to profile/level.
+Once decoded_picture_buffer is allocated, Sl,Scb,Scr in
+AVCPictureData structure just point to the address in decoded_picture_buffer.
+used_size maintains the used space.
+NOTE:: In order to maintain contiguous memory space, memory equal to a single frame is
+assigned at a time. Two opposite fields reside in the same frame memory.
+
+ |-------|---|---|---|xxx|-------|xxx|---|-------| decoded_picture_buffer
+ frame top bot top frame bot frame
+ 0 1 1 2 3 4 5
+
+ bot 2 and top 4 do not exist, the memory is not used.
+
+@publishedAll
+*/
+typedef struct tagDecPicBuffer
+{
+ uint8 *decoded_picture_buffer; /* actual memory */
+ uint32 dpb_size; /* size of dpb in bytes */
+ uint32 used_size; /* used size */
+ struct tagFrameStore *fs[MAX_FS]; /* list of frame stored, actual buffer */
+ int num_fs; /* size of fs */
+
+} AVCDecPicBuffer;
+
+
+/**
+This structure contains macroblock related variables.
+@publishedAll
+*/
+typedef struct tagMacroblock
+{
+ AVCIntraChromaPredMode intra_chroma_pred_mode; /* ue(v) */
+
+ int32 mvL0[16]; /* motion vectors, 16 bit packed (x,y) per element */
+ int32 mvL1[16];
+ int16 ref_idx_L0[4];
+ int16 ref_idx_L1[4];
+ uint16 RefIdx[4]; /* ref index, has value of AVCPictureData->RefIdx */
+ /* stored data */
+ /*bool*/
+ uint mb_intra; /* intra flag */
+ /*bool*/
+ uint mb_bottom_field;
+
+ AVCMBMode mbMode; /* type of MB prediction */
+ AVCSubMBMode subMbMode[4]; /* for each 8x8 partition */
+
+ uint CBP; /* CodeBlockPattern */
+ AVCIntra16x16PredMode i16Mode; /* Intra16x16PredMode */
+ AVCIntra4x4PredMode i4Mode[16]; /* Intra4x4PredMode, in raster scan order */
+ int NumMbPart; /* number of partition */
+ AVCPredMode MBPartPredMode[4][4]; /* prediction mode [MBPartIndx][subMBPartIndx] */
+ int MbPartWidth;
+ int MbPartHeight;
+ int NumSubMbPart[4]; /* for each 8x8 partition */
+ int SubMbPartWidth[4]; /* for each 8x8 partition */
+ int SubMbPartHeight[4]; /* for each 8x8 partition */
+
+ uint8 nz_coeff[NUM_BLKS_IN_MB]; /* [blk_y][blk_x], Chroma is [4..5][0...3], see predict_nnz() function */
+
+ int QPy; /* Luma QP */
+ int QPc; /* Chroma QP */
+ int QSc; /* Chroma QP S-picture */
+
+ int slice_id; // MC slice
+} AVCMacroblock;
+
+
+/**
+This structure contains common internal variables between the encoder and decoder
+such that some functions can be shared among them.
+@publishedAll
+*/
+typedef struct tagCommonObj
+{
+ /* put these 2 up here to make sure they are word-aligned */
+ int16 block[NUM_PIXELS_IN_MB]; /* for transformed residue coefficient */
+ uint8 *pred_block; /* pointer to prediction block, could point to a frame */
+#ifdef USE_PRED_BLOCK
+ uint8 pred[688]; /* for prediction */
+ /* Luma [0-399], Cb [400-543], Cr[544-687] */
+#endif
+ int pred_pitch; /* either equal to 20 or to frame pitch */
+
+ /* temporary buffers for intra prediction */
+ /* these variables should remain inside fast RAM */
+#ifdef MB_BASED_DEBLOCK
+ uint8 *intra_pred_top; /* a row of pixel for intra prediction */
+ uint8 intra_pred_left[17]; /* a column of pixel for intra prediction */
+ uint8 *intra_pred_top_cb;
+ uint8 intra_pred_left_cb[9];
+ uint8 *intra_pred_top_cr;
+ uint8 intra_pred_left_cr[9];
+#endif
+ /* pointer to the prediction area for intra prediction */
+ uint8 *pintra_pred_top; /* pointer to the top intra prediction value */
+ uint8 *pintra_pred_left; /* pointer to the left intra prediction value */
+ uint8 intra_pred_topleft; /* the [-1,-1] neighboring pixel */
+ uint8 *pintra_pred_top_cb;
+ uint8 *pintra_pred_left_cb;
+ uint8 intra_pred_topleft_cb;
+ uint8 *pintra_pred_top_cr;
+ uint8 *pintra_pred_left_cr;
+ uint8 intra_pred_topleft_cr;
+
+ int QPy;
+ int QPc;
+ int QPy_div_6;
+ int QPy_mod_6;
+ int QPc_div_6;
+ int QPc_mod_6;
+ /**** nal_unit ******/
+ /* previously in AVCNALUnit format */
+ uint NumBytesInRBSP;
+ int forbidden_bit;
+ int nal_ref_idc;
+ AVCNalUnitType nal_unit_type;
+ AVCNalUnitType prev_nal_unit_type;
+ /*bool*/
+ uint slice_data_partitioning; /* flag when nal_unit_type is between 2 and 4 */
+ /**** ******** ******/
+ AVCSliceType slice_type;
+ AVCDecPicBuffer *decPicBuf; /* decoded picture buffer */
+
+ AVCSeqParamSet *currSeqParams; /* the currently used one */
+
+ AVCPicParamSet *currPicParams; /* the currently used one */
+ uint seq_parameter_set_id;
+ /* slice header */
+ AVCSliceHeader *sliceHdr; /* slice header param syntax variables */
+
+ AVCPictureData *currPic; /* pointer to current picture */
+ AVCFrameStore *currFS; /* pointer to current frame store */
+ AVCPictureType currPicType; /* frame, top-field or bot-field */
+ /*bool*/
+ uint newPic; /* flag for new picture */
+ uint newSlice; /* flag for new slice */
+ AVCPictureData *prevRefPic; /* pointer to previous picture */
+
+ AVCMacroblock *mblock; /* array of macroblocks covering entire picture */
+ AVCMacroblock *currMB; /* pointer to current macroblock */
+ uint mbNum; /* number of current MB */
+ int mb_x; /* x-coordinate of the current mbNum */
+ int mb_y; /* y-coordinate of the current mbNum */
+
+ /* For internal operation, scratch memory for MV, prediction, transform, etc.*/
+ uint32 cbp4x4; /* each bit represent nonzero 4x4 block in reverse raster scan order */
+ /* starting from luma, Cb and Cr, lsb toward msb */
+ int mvd_l0[4][4][2]; /* [mbPartIdx][subMbPartIdx][compIdx], se(v) */
+ int mvd_l1[4][4][2]; /* [mbPartIdx][subMbPartIdx][compIdx], se(v) */
+
+ int mbAddrA, mbAddrB, mbAddrC, mbAddrD; /* address of neighboring MBs */
+ /*bool*/
+ uint mbAvailA, mbAvailB, mbAvailC, mbAvailD; /* availability */
+ /*bool*/
+ uint intraAvailA, intraAvailB, intraAvailC, intraAvailD; /* for intra mode */
+ /***********************************************/
+ /* The following variables are defined in the draft. */
+ /* They may need to be stored in PictureData structure and used for reference. */
+ /* In that case, just move or copy it to AVCDecPictureData structure. */
+
+ int padded_size; /* size of extra padding to a frame */
+
+ uint MaxFrameNum; /*2^(log2_max_frame_num_minus4+4), range 0.. 2^16-1 */
+ uint MaxPicOrderCntLsb; /*2^(log2_max_pic_order_cnt_lsb_minus4+4), 0..2^16-1 */
+ uint PicWidthInMbs; /*pic_width_in_mbs_minus1+1 */
+ uint PicWidthInSamplesL; /* PicWidthInMbs*16 */
+ uint PicWidthInSamplesC; /* PicWIdthInMbs*8 */
+ uint PicHeightInMapUnits; /* pic_height_in_map_units_minus1+1 */
+ uint PicSizeInMapUnits; /* PicWidthInMbs*PicHeightInMapUnits */
+ uint FrameHeightInMbs; /*(2-frame_mbs_only_flag)*PicHeightInMapUnits */
+
+ uint SliceGroupChangeRate; /* slice_group_change_rate_minus1 + 1 */
+
+ /* access unit */
+ uint primary_pic_type; /* u(3), Table 7-2, kinda informative only */
+
+ /* slice data partition */
+ uint slice_id; /* ue(v) */
+
+ uint UnusedShortTermFrameNum;
+ uint PrevRefFrameNum;
+ uint MbaffFrameFlag; /* (mb_adaptive_frame_field_flag && !field_pic_flag) */
+ uint PicHeightInMbs; /* FrameHeightInMbs/(1+field_pic_flag) */
+ int PicHeightInSamplesL; /* PicHeightInMbs*16 */
+ int PicHeightInSamplesC; /* PicHeightInMbs*8 */
+ uint PicSizeInMbs; /* PicWidthInMbs*PicHeightInMbs */
+ uint level_idc;
+ int numMBs;
+ uint MaxPicNum;
+ uint CurrPicNum;
+ int QSy; /* 26+pic_init_qp_minus26+slice_qs_delta */
+ int FilterOffsetA;
+ int FilterOffsetB;
+ uint MapUnitsInSliceGroup0; /* Min(slie_group_change_cycle*SliceGroupChangeRate,PicSizeInMapUnits) */
+ /* dec_ref_pic_marking */
+ int MaxLongTermFrameIdx;
+ int LongTermFrameIdx;
+
+ /* POC related variables */
+ /*bool*/
+ uint mem_mgr_ctrl_eq_5; /* if memory_management_control_operation equal to 5 flag */
+ int PicOrderCnt;
+ int BottomFieldOrderCnt, TopFieldOrderCnt;
+ /* POC mode 0 */
+ int prevPicOrderCntMsb;
+ uint prevPicOrderCntLsb;
+ int PicOrderCntMsb;
+ /* POC mode 1 */
+ int prevFrameNumOffset, FrameNumOffset;
+ uint prevFrameNum;
+ int absFrameNum;
+ int picOrderCntCycleCnt, frameNumInPicOrderCntCycle;
+ int expectedDeltaPerPicOrderCntCycle;
+ int expectedPicOrderCnt;
+
+ /* FMO */
+ int *MbToSliceGroupMap; /* to be re-calculate at the beginning */
+
+ /* ref pic list */
+ AVCPictureData *RefPicList0[MAX_REF_PIC_LIST]; /* list 0 */
+ AVCPictureData *RefPicList1[MAX_REF_PIC_LIST]; /* list 1 */
+ AVCFrameStore *refFrameList0ShortTerm[32];
+ AVCFrameStore *refFrameList1ShortTerm[32];
+ AVCFrameStore *refFrameListLongTerm[32];
+ int refList0Size;
+ int refList1Size;
+
+ /* slice data semantics*/
+ int mb_skip_run; /* ue(v) */
+ /*uint mb_skip_flag;*/ /* ae(v) */
+ /* uint end_of_slice_flag;*//* ae(v) */
+ /***********************************************/
+
+ /* function pointers */
+ int (*is_short_ref)(AVCPictureData *s);
+ int (*is_long_ref)(AVCPictureData *s);
+
+} AVCCommonObj;
+
+/**
+Commonly used constant arrays.
+@publishedAll
+*/
+/**
+Zigzag scan from 1-D to 2-D. */
+const static uint8 ZZ_SCAN[16] = {0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15};
+/* Zigzag scan from 1-D to 2-D output to block[24][16]. */
+const static uint8 ZZ_SCAN_BLOCK[16] = {0, 1, 16, 32, 17, 2, 3, 18, 33, 48, 49, 34, 19, 35, 50, 51};
+
+/**
+From zigzag to raster for luma DC value */
+const static uint8 ZIGZAG2RASTERDC[16] = {0, 4, 64, 128, 68, 8, 12, 72, 132, 192, 196, 136, 76, 140, 200, 204};
+
+
+/**
+Mapping from coding scan block indx to raster scan block index */
+const static int blkIdx2blkX[16] = {0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3};
+const static int blkIdx2blkY[16] = {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3};
+/** from [blk8indx][blk4indx] to raster scan index */
+const static int blkIdx2blkXY[4][4] = {{0, 1, 4, 5}, {2, 3, 6, 7}, {8, 9, 12, 13}, {10, 11, 14, 15}};
+
+/*
+Availability of the neighboring top-right block relative to the current block. */
+const static int BlkTopRight[16] = {2, 2, 2, 3, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0};
+
+/**
+Table 8-13 Specification of QPc as a function of qPI. */
+const static uint8 mapQPi2QPc[52] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36,
+ 37, 37, 37, 38, 38, 38, 39, 39, 39, 39
+ };
+
+/**
+See 8.5.5 equation (8-252 and 8-253) the definition of v matrix. */
+/* in zigzag scan */
+const static int dequant_coefres[6][16] =
+{
+ {10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16},
+ {11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18},
+ {13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20},
+ {14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23},
+ {16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25},
+ {18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29}
+};
+
+/**
+From jm7.6 block.c. (in zigzag scan) */
+const static int quant_coef[6][16] =
+{
+ {13107, 8066, 8066, 13107, 5243, 13107, 8066, 8066, 8066, 8066, 5243, 13107, 5243, 8066, 8066, 5243},
+ {11916, 7490, 7490, 11916, 4660, 11916, 7490, 7490, 7490, 7490, 4660, 11916, 4660, 7490, 7490, 4660},
+ {10082, 6554, 6554, 10082, 4194, 10082, 6554, 6554, 6554, 6554, 4194, 10082, 4194, 6554, 6554, 4194},
+ {9362, 5825, 5825, 9362, 3647, 9362, 5825, 5825, 5825, 5825, 3647, 9362, 3647, 5825, 5825, 3647},
+ {8192, 5243, 5243, 8192, 3355, 8192, 5243, 5243, 5243, 5243, 3355, 8192, 3355, 5243, 5243, 3355},
+ {7282, 4559, 4559, 7282, 2893, 7282, 4559, 4559, 4559, 4559, 2893, 7282, 2893, 4559, 4559, 2893}
+};
+
+/**
+Convert scan from raster scan order to block decoding order and
+from block decoding order to raster scan order. Same table!!!
+*/
+const static uint8 ras2dec[16] = {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
+
+/* mapping from level_idc to index map */
+const static uint8 mapLev2Idx[61] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 1,
+ 0, 1, 2, 3, 255, 255, 255, 255, 255, 255,
+ 4, 5, 6, 255, 255, 255, 255, 255, 255, 255,
+ 7, 8, 9, 255, 255, 255, 255, 255, 255, 255,
+ 10, 11, 12, 255, 255, 255, 255, 255, 255, 255,
+ 13, 14, 255, 255, 255, 255, 255, 255, 255, 255
+ };
+/* map back from index to Level IDC */
+const static uint8 mapIdx2Lev[MAX_LEVEL_IDX] = {10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51};
+
+/**
+from the index map to the MaxDPB value times 2 */
+const static int32 MaxDPBX2[MAX_LEVEL_IDX] = {297, 675, 1782, 1782, 1782, 3564, 6075, 6075,
+ 13500, 15360, 24576, 24576, 24576, 82620, 138240
+ };
+
+/* map index to the max frame size */
+const static int MaxFS[MAX_LEVEL_IDX] = {99, 396, 396, 396, 396, 792, 1620, 1620, 3600, 5120,
+ 8192, 8192, 8192, 22080, 36864
+ };
+
+/* map index to max MB processing rate */
+const static int32 MaxMBPS[MAX_LEVEL_IDX] = {1485, 3000, 6000, 11880, 11880, 19800, 20250, 40500,
+ 108000, 216000, 245760, 245760, 491520, 589824, 983040
+ };
+
+/* map index to max video bit rate */
+const static uint32 MaxBR[MAX_LEVEL_IDX] = {64, 192, 384, 768, 2000, 4000, 4000, 10000, 14000, 20000,
+ 20000, 50000, 50000, 135000, 240000
+ };
+
+/* map index to max CPB size */
+const static uint32 MaxCPB[MAX_LEVEL_IDX] = {175, 500, 1000, 2000, 2000, 4000, 4000, 10000, 14000,
+ 20000, 25000, 62500, 62500, 135000, 240000
+ };
+
+/* map index to max vertical MV range */
+const static int MaxVmvR[MAX_LEVEL_IDX] = {64, 128, 128, 128, 128, 256, 256, 256, 512, 512, 512, 512, 512, 512, 512};
+
+#endif /* _AVCINT_COMMON_H_ */
diff --git a/media/libstagefright/codecs/avc/common/include/avclib_common.h b/media/libstagefright/codecs/avc/common/include/avclib_common.h
new file mode 100644
index 0000000..e98396e
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avclib_common.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 common encoder/decoder library.
+@publishedAll
+*/
+#ifndef AVCCOMMON_LIB_H_INCLUDED
+#define AVCCOMMON_LIB_H_INCLUDED
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#include "avcint_common.h"
+#endif
+
+/*----------- deblock.c --------------*/
+/**
+This function performs conditional deblocking on a complete picture.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+OSCL_IMPORT_REF AVCStatus DeblockPicture(AVCCommonObj *video);
+
+/**
+This function performs MB-based deblocking when MB_BASED_DEBLOCK
+is defined at compile time.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+void MBInLoopDeblock(AVCCommonObj *video);
+
+
+/*---------- dpb.c --------------------*/
+/**
+This function is called everytime a new sequence is detected.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\param "padding" "Flag specifying whether padding in luma component is needed (used for encoding)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus AVCConfigureSequence(AVCHandle *avcHandle, AVCCommonObj *video, bool padding);
+
+/**
+This function allocates and initializes the decoded picture buffer structure based on
+the profile and level for the first sequence parameter set. Currently,
+it does not allow changing in profile/level for subsequent SPS.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\param "FrameHeightInMbs" "Height of the frame in the unit of MBs."
+\param "PicWidthInMbs" "Width of the picture in the unit of MBs."
+\param "padding" "Flag specifying whether padding in luma component is needed (used for encoding)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+AVCStatus InitDPB(AVCHandle *avcHandle, AVCCommonObj *video, int FrameHeightInMbs, int PicWidthInMbs, bool padding);
+
+/**
+This function frees the DPB memory.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus CleanUpDPB(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function finds empty frame in the decoded picture buffer to be used for the
+current picture, initializes the corresponding picture structure with Sl, Scb, Scr,
+width, height and pitch.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus DPBInitBuffer(AVCHandle *avcHandle, AVCCommonObj *video);
+/**
+This function finds empty frame in the decoded picture buffer to be used for the
+current picture, initializes the corresponding picture structure with Sl, Scb, Scr,
+width, height and pitch.
+\param "video" "Pointer to AVCCommonObj."
+\param "CurrPicNum" "Current picture number (only used in decoder)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+
+OSCL_IMPORT_REF void DPBInitPic(AVCCommonObj *video, int CurrPicNum);
+
+/**
+This function releases the current frame back to the available pool for skipped frame after encoding.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\return "void."
+*/
+OSCL_IMPORT_REF void DPBReleaseCurrentFrame(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function performs decoded reference picture marking process and store the current picture to the
+corresponding frame storage in the decoded picture buffer.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus StorePictureInDPB(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function perform sliding window operation on the reference picture lists, see subclause 8.2.5.3.
+It removes short-term ref frames with smallest FrameNumWrap from the reference list.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\return "AVC_SUCCESS or AVC_FAIL (contradicting values or scenario as in the Note in the draft)."
+*/
+AVCStatus sliding_window_process(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb);
+
+
+/**
+This function perform adaptive memory marking operation on the reference picture lists,
+see subclause 8.2.5.4. It calls other functions for specific operations.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "sliceHdr" "Pointer to the AVCSliceHeader."
+\return "AVC_SUCCESS or AVC_FAIL (contradicting values or scenario as in the Note in the draft)."
+*/
+AVCStatus adaptive_memory_marking(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, AVCSliceHeader *sliceHdr);
+
+/**
+This function performs memory management control operation 1, marking a short-term picture
+as unused for reference. See subclause 8.2.5.4.1.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "difference_of_pic_nums_minus1" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp1(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, int difference_of_pic_nums_minus1);
+
+/**
+This function performs memory management control operation 2, marking a long-term picture
+as unused for reference. See subclause 8.2.5.4.2.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "field_pic_flag" "Flag whether the current picture is field or not."
+\param "long_term_pic_num" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp2(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, int long_term_pic_num);
+
+/**
+This function performs memory management control operation 3, assigning a LongTermFrameIdx to
+a short-term reference picture. See subclause 8.2.5.4.3.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "difference_of_pic_nums_minus1" "From the syntax in dec_ref_pic_marking()."
+\param "long_term_pic_num" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp3(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint difference_of_pic_nums_minus1,
+ uint long_term_frame_idx);
+
+/**
+This function performs memory management control operation 4, getting new MaxLongTermFrameIdx.
+ See subclause 8.2.5.4.4.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "max_long_term_frame_idx_plus1" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp4(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint max_long_term_frame_idx_plus1);
+
+/**
+This function performs memory management control operation 5, marking all reference pictures
+as unused for reference and set MaxLongTermFrameIdx to no long-termframe indices.
+ See subclause 8.2.5.4.5.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+*/
+void MemMgrCtrlOp5(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb);
+
+/**
+This function performs memory management control operation 6, assigning a long-term frame index
+to the current picture. See subclause 8.2.5.4.6.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp6(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_idx);
+
+/**
+This function mark a long-term ref frame with a specific frame index as unused for reference.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "To look for"
+*/
+void unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint long_term_frame_idx);
+
+/**
+This function mark a long-term ref field with a specific frame index as unused for reference except
+a frame that contains a picture with picNumX.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "To look for."
+\param "picNumX" "To look for."
+*/
+void unmark_long_term_field_for_reference_by_frame_idx(AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_indx, int picNumX);
+
+/**
+This function mark a frame to unused for reference.
+\param "fs" "Pointer to AVCFrameStore to be unmarked."
+*/
+void unmark_for_reference(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint idx);
+
+void update_ref_list(AVCDecPicBuffer *dpb);
+
+
+/*---------- fmo.c --------------*/
+/**
+This function initializes flexible macroblock reordering.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+OSCL_IMPORT_REF AVCStatus FMOInit(AVCCommonObj *video);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the interleaved slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "run_length_minus1" "Array of the run-length."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType0MapUnitMap(int *mapUnitToSliceGroupMap, uint *run_length_minus1, uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the dispersed slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType1MapUnitMap(int *mapUnitToSliceGroupMap, int PicWidthInMbs, uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the foreground with left-over slice group map type.
+\param "pps" "Pointer to AVCPicParamSets structure."
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType2MapUnitMap(AVCPicParamSet *pps, int *mapUnitToSliceGroupMap, int PicWidthInMbs,
+ uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the box-out slice group map type.
+\param "pps" "Pointer to AVCPicParamSets structure."
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\return "Void."
+*/
+void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
+ int PicWidthInMbs);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the raster scan slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "MapUnitsInSliceGroup0" "Derived in subclause 7.4.3."
+\param "slice_group_change_direction_flag" "A value from the slice header."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType4MapUnitMap(int *mapUnitToSliceGroupMap, int MapUnitsInSliceGroup0,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following wipe slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "video" "Pointer to AVCCommonObj structure."
+\param "slice_group_change_direction_flag" "A value from the slice header."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType5MapUnitMap(int *mapUnitsToSliceGroupMap, AVCCommonObj *video,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following wipe slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "slice_group_id" "Array of slice_group_id from AVCPicParamSet structure."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType6MapUnitMap(int *mapUnitsToSliceGroupMap, int *slice_group_id, uint PicSizeInMapUnits);
+
+/*------------- itrans.c --------------*/
+/**
+This function performs transformation of the Intra16x16DC value according to
+subclause 8.5.6.
+\param "block" "Pointer to the video->block[0][0][0]."
+\param "QPy" "Quantization parameter."
+\return "void."
+*/
+void Intra16DCTrans(int16 *block, int Qq, int Rq);
+
+/**
+This function performs transformation of a 4x4 block according to
+subclause 8.5.8.
+\param "block" "Pointer to the origin of transform coefficient area."
+\param "pred" "Pointer to the origin of predicted area."
+\param "cur" "Pointer to the origin of the output area."
+\param "width" "Pitch of cur."
+\return "void."
+*/
+void itrans(int16 *block, uint8 *pred, uint8 *cur, int width);
+
+/*
+This function is the same one as itrans except for chroma.
+\param "block" "Pointer to the origin of transform coefficient area."
+\param "pred" "Pointer to the origin of predicted area."
+\param "cur" "Pointer to the origin of the output area."
+\param "width" "Pitch of cur."
+\return "void."
+*/
+void ictrans(int16 *block, uint8 *pred, uint8 *cur, int width);
+
+/**
+This function performs transformation of the DCChroma value according to
+subclause 8.5.7.
+\param "block" "Pointer to the video->block[0][0][0]."
+\param "QPc" "Quantization parameter."
+\return "void."
+*/
+void ChromaDCTrans(int16 *block, int Qq, int Rq);
+
+/**
+This function copies a block from pred to cur.
+\param "pred" "Pointer to prediction block."
+\param "cur" "Pointer to the current YUV block."
+\param "width" "Pitch of cur memory."
+\param "pred_pitch" "Pitch for pred memory.
+\return "void."
+*/
+void copy_block(uint8 *pred, uint8 *cur, int width, int pred_pitch);
+
+/*--------- mb_access.c ----------------*/
+/**
+This function initializes the neighboring information before start macroblock decoding.
+\param "video" "Pointer to AVCCommonObj."
+\param "mbNum" "The current macroblock index."
+\param "currMB" "Pointer to the current AVCMacroblock structure."
+\return "void"
+*/
+OSCL_IMPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum);
+
+/**
+This function checks whether the requested neighboring macroblock is available.
+\param "MbToSliceGroupMap" "Array containing the slice group ID mapping to MB index."
+\param "PicSizeInMbs" "Size of the picture in number of MBs."
+\param "mbAddr" "Neighboring macroblock index to check."
+\param "currMbAddr" "Current macroblock index."
+\return "TRUE if the neighboring MB is available, FALSE otherwise."
+*/
+bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr);
+
+/**
+This function performs prediction of the nonzero coefficient for a luma block (i,j).
+\param "video" "Pointer to AVCCommonObj."
+\param "i" "Block index, horizontal."
+\param "j" "Block index, vertical."
+\return "Predicted number of nonzero coefficient."
+*/
+OSCL_IMPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j);
+
+/**
+This function performs prediction of the nonzero coefficient for a chroma block (i,j).
+\param "video" "Pointer to AVCCommonObj."
+\param "i" "Block index, horizontal."
+\param "j" "Block index, vertical."
+\return "Predicted number of nonzero coefficient."
+*/
+OSCL_IMPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j);
+
+/**
+This function calculates the predicted motion vectors for the current macroblock.
+\param "video" "Pointer to AVCCommonObj."
+\param "encFlag" "Boolean whether this function is used by encoder or decoder."
+\return "void."
+*/
+OSCL_IMPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag);
+
+/*---------- reflist.c -----------------*/
+/**
+This function initializes reference picture list used in INTER prediction
+at the beginning of each slice decoding. See subclause 8.2.4.
+\param "video" "Pointer to AVCCommonObj."
+\return "void"
+Output is video->RefPicList0, video->RefPicList1, video->refList0Size and video->refList1Size.
+*/
+OSCL_IMPORT_REF void RefListInit(AVCCommonObj *video);
+
+/**
+This function generates picture list from frame list. Used when current picture is field.
+see subclause 8.2.4.2.5.
+\param "video" "Pointer to AVCCommonObj."
+\param "IsL1" "Is L1 list?"
+\param "long_term" "Is long-term prediction?"
+\return "void"
+*/
+void GenPicListFromFrameList(AVCCommonObj *video, int IsL1, int long_term);
+
+/**
+This function performs reference picture list reordering according to the
+ref_pic_list_reordering() syntax. See subclause 8.2.4.3.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL"
+Output is video->RefPicList0, video->RefPicList1, video->refList0Size and video->refList1Size.
+*/
+OSCL_IMPORT_REF AVCStatus ReOrderList(AVCCommonObj *video);
+
+/**
+This function performs reference picture list reordering according to the
+ref_pic_list_reordering() syntax regardless of list 0 or list 1. See subclause 8.2.4.3.
+\param "video" "Pointer to AVCCommonObj."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+Output is video->RefPicList0 and video->refList0Size or video->RefPicList1 and video->refList1Size.
+*/
+AVCStatus ReorderRefPicList(AVCCommonObj *video, int isL1);
+
+/**
+This function performs reordering process of reference picture list for short-term pictures.
+See subclause 8.2.4.3.1.
+\param "video" "Pointer to AVCCommonObj."
+\param "picNumLX" "picNumLX of an entry in the reference list."
+\param "refIdxLX" "Pointer to the current entry index in the reference."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+*/
+AVCStatus ReorderShortTerm(AVCCommonObj *video, int picNumLX, int *refIdxLX, int isL1);
+
+/**
+This function performs reordering process of reference picture list for long-term pictures.
+See subclause 8.2.4.3.2.
+\param "video" "Pointer to AVCCommonObj."
+\param "LongTermPicNum" "LongTermPicNum of an entry in the reference list."
+\param "refIdxLX" "Pointer to the current entry index in the reference."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+*/
+AVCStatus ReorderLongTerm(AVCCommonObj *video, int LongTermPicNum, int *refIdxLX, int isL1);
+
+/**
+This function gets the pictures in DPB according to the PicNum.
+\param "video" "Pointer to AVCCommonObj."
+\param "picNum" "PicNum of the picture we are looking for."
+\return "Pointer to the AVCPictureData or NULL if not found"
+*/
+AVCPictureData* GetShortTermPic(AVCCommonObj *video, int picNum);
+
+/**
+This function gets the pictures in DPB according to the LongtermPicNum.
+\param "video" "Pointer to AVCCommonObj."
+\param "LongtermPicNum" "LongtermPicNum of the picture we are looking for."
+\return "Pointer to the AVCPictureData."
+*/
+AVCPictureData* GetLongTermPic(AVCCommonObj *video, int LongtermPicNum);
+
+/**
+This function indicates whether the picture is used for short-term reference or not.
+\param "s" "Pointer to AVCPictureData."
+\return "1 if it is used for short-term, 0 otherwise."
+*/
+int is_short_ref(AVCPictureData *s);
+
+/**
+This function indicates whether the picture is used for long-term reference or not.
+\param "s" "Pointer to AVCPictureData."
+\return "1 if it is used for long-term, 0 otherwise."
+*/
+int is_long_ref(AVCPictureData *s);
+
+/**
+This function sorts array of pointers to AVCPictureData in descending order of
+the PicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPicNum(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCPictureData in ascending order of
+the PicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPicNumLongTerm(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in descending order of
+the FrameNumWrap value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByFrameNumWrap(AVCFrameStore *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in ascending order of
+the LongTermFrameIdx value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByLTFrameIdx(AVCFrameStore *data[], int num);
+
+/**
+This function sorts array of pointers to AVCPictureData in descending order of
+the PicOrderCnt value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPOC(AVCPictureData *data[], int num, int descending);
+
+/**
+This function sorts array of pointers to AVCPictureData in ascending order of
+the LongTermPicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByLTPicNum(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in descending order of
+the PicOrderCnt value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByPOC(AVCFrameStore *data[], int num, int descending);
+
+
+#endif /* _AVCCOMMON_LIB_H_ */
diff --git a/media/libstagefright/codecs/avc/common/src/deblock.cpp b/media/libstagefright/codecs/avc/common/src/deblock.cpp
new file mode 100644
index 0000000..5ed4c82
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/deblock.cpp
@@ -0,0 +1,1666 @@
+/* ------------------------------------------------------------------
+ * 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 "avclib_common.h"
+
+#define MAX_QP 51
+#define MB_BLOCK_SIZE 16
+
+// NOTE: these 3 tables are for funtion GetStrength() only
+const static int ININT_STRENGTH[4] = {0x04040404, 0x03030303, 0x03030303, 0x03030303};
+
+
+// NOTE: these 3 tables are for funtion EdgeLoop() only
+// NOTE: to change the tables below for instance when the QP doubling is changed from 6 to 8 values
+
+const static int ALPHA_TABLE[52] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226, 255, 255} ;
+const static int BETA_TABLE[52] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18} ;
+const static int CLIP_TAB[52][5] =
+{
+ { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 1, 1, 1, 1},
+ { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 2, 3, 3},
+ { 0, 1, 2, 3, 3}, { 0, 2, 2, 3, 3}, { 0, 2, 2, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 3, 3, 5, 5}, { 0, 3, 4, 6, 6}, { 0, 3, 4, 6, 6},
+ { 0, 4, 5, 7, 7}, { 0, 4, 5, 8, 8}, { 0, 4, 6, 9, 9}, { 0, 5, 7, 10, 10}, { 0, 6, 8, 11, 11}, { 0, 6, 8, 13, 13}, { 0, 7, 10, 14, 14}, { 0, 8, 11, 16, 16},
+ { 0, 9, 12, 18, 18}, { 0, 10, 13, 20, 20}, { 0, 11, 15, 23, 23}, { 0, 13, 17, 25, 25}
+};
+
+// NOTE: this table is only QP clipping, index = QP + video->FilterOffsetA/B, clipped to [0, 51]
+// video->FilterOffsetA/B is in {-12, 12]
+const static int QP_CLIP_TAB[76] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [-12, 0]
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // [1, 51]
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51 // [52,63]
+};
+
+static void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV);
+//static void GetStrength(AVCCommonObj *video, uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir, int edge);
+static void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir);
+static void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ);
+static void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ);
+static void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+
+/*
+ *****************************************************************************************
+ * \brief Filter all macroblocks in order of increasing macroblock address.
+ *****************************************************************************************
+*/
+
+OSCL_EXPORT_REF AVCStatus DeblockPicture(AVCCommonObj *video)
+{
+ uint i, j;
+ int pitch = video->currPic->pitch, pitch_c, width;
+ uint8 *SrcY, *SrcU, *SrcV;
+
+ SrcY = video->currPic->Sl; // pointers to source
+ SrcU = video->currPic->Scb;
+ SrcV = video->currPic->Scr;
+ pitch_c = pitch >> 1;
+ width = video->currPic->width;
+
+ for (i = 0; i < video->PicHeightInMbs; i++)
+ {
+ for (j = 0; j < video->PicWidthInMbs; j++)
+ {
+ DeblockMb(video, j, i, SrcY, SrcU, SrcV);
+ // update SrcY, SrcU, SrcV
+ SrcY += MB_BLOCK_SIZE;
+ SrcU += (MB_BLOCK_SIZE >> 1);
+ SrcV += (MB_BLOCK_SIZE >> 1);
+ }
+
+ SrcY += ((pitch << 4) - width);
+ SrcU += ((pitch_c << 3) - (width >> 1));
+ SrcV += ((pitch_c << 3) - (width >> 1));
+ }
+
+ return AVC_SUCCESS;
+}
+
+#ifdef MB_BASED_DEBLOCK
+/*
+ *****************************************************************************************
+ * \brief Filter one macroblocks in a fast macroblock memory and copy it to frame
+ *****************************************************************************************
+*/
+void MBInLoopDeblock(AVCCommonObj *video)
+{
+ AVCPictureData *currPic = video->currPic;
+#ifdef USE_PRED_BLOCK
+ uint8 *predCb, *predCr, *pred_block;
+ int i, j, dst_width, dst_height, dst_widthc, dst_heightc;
+#endif
+ int pitch = currPic->pitch;
+ int x_pos = video->mb_x;
+ int y_pos = video->mb_y;
+ uint8 *curL, *curCb, *curCr;
+ int offset;
+
+ offset = (y_pos << 4) * pitch;
+
+ curL = currPic->Sl + offset + (x_pos << 4);
+
+ offset >>= 2;
+ offset += (x_pos << 3);
+
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+
+#ifdef USE_PRED_BLOCK
+ pred_block = video->pred;
+
+ /* 1. copy neighboring pixels from frame to the video->pred_block */
+ if (y_pos) /* not the 0th row */
+ {
+ /* copy to the top 4 lines of the macroblock */
+ curL -= (pitch << 2); /* go back 4 lines */
+
+ memcpy(pred_block + 4, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 24, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 44, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 64, curL, 16);
+ curL += pitch;
+
+ curCb -= (pitch << 1); /* go back 4 lines chroma */
+ curCr -= (pitch << 1);
+
+ pred_block += 400;
+
+ memcpy(pred_block + 4, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 16, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 28, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 40, curCb, 8);
+ curCb += (pitch >> 1);
+
+ pred_block += 144;
+ memcpy(pred_block + 4, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 16, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 28, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 40, curCr, 8);
+ curCr += (pitch >> 1);
+
+ pred_block = video->pred;
+ }
+
+ /* 2. perform deblocking. */
+ DeblockMb(video, x_pos, y_pos, pred_block + 84, pred_block + 452, pred_block + 596);
+
+ /* 3. copy it back to the frame and update pred_block */
+ predCb = pred_block + 400;
+ predCr = predCb + 144;
+
+ /* find the range of the block inside pred_block to be copied back */
+ if (y_pos) /* the first row */
+ {
+ curL -= (pitch << 2);
+ curCb -= (pitch << 1);
+ curCr -= (pitch << 1);
+
+ dst_height = 20;
+ dst_heightc = 12;
+ }
+ else
+ {
+ pred_block += 80;
+ predCb += 48;
+ predCr += 48;
+ dst_height = 16;
+ dst_heightc = 8;
+ }
+
+ if (x_pos) /* find the width */
+ {
+ curL -= 4;
+ curCb -= 4;
+ curCr -= 4;
+ if (x_pos == (int)(video->PicWidthInMbs - 1))
+ {
+ dst_width = 20;
+ dst_widthc = 12;
+ }
+ else
+ {
+ dst_width = 16;
+ dst_widthc = 8;
+ }
+ }
+ else
+ {
+ pred_block += 4;
+ predCb += 4;
+ predCr += 4;
+ dst_width = 12;
+ dst_widthc = 4;
+ }
+
+ /* perform copy */
+ for (j = 0; j < dst_height; j++)
+ {
+ memcpy(curL, pred_block, dst_width);
+ curL += pitch;
+ pred_block += 20;
+ }
+ for (j = 0; j < dst_heightc; j++)
+ {
+ memcpy(curCb, predCb, dst_widthc);
+ memcpy(curCr, predCr, dst_widthc);
+ curCb += (pitch >> 1);
+ curCr += (pitch >> 1);
+ predCb += 12;
+ predCr += 12;
+ }
+
+ if (x_pos != (int)(video->PicWidthInMbs - 1)) /* now copy from the right-most 4 columns to the left-most 4 columns */
+ {
+ pred_block = video->pred;
+ for (i = 0; i < 20; i += 4)
+ {
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ }
+
+ for (i = 0; i < 24; i += 4)
+ {
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ }
+
+ }
+#else
+ DeblockMb(video, x_pos, y_pos, curL, curCb, curCr);
+#endif
+
+ return ;
+}
+#endif
+
+/*
+ *****************************************************************************************
+ * \brief Deblocking filter for one macroblock.
+ *****************************************************************************************
+ */
+
+void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV)
+{
+ AVCMacroblock *MbP, *MbQ;
+ int edge, QP, QPC;
+ int filterLeftMbEdgeFlag = (mb_x != 0);
+ int filterTopMbEdgeFlag = (mb_y != 0);
+ int pitch = video->currPic->pitch;
+ int indexA, indexB, tmp;
+ int Alpha, Beta, Alpha_c, Beta_c;
+ int mbNum = mb_y * video->PicWidthInMbs + mb_x;
+ int *clipTable, *clipTable_c, *qp_clip_tab;
+ uint8 Strength[16];
+ void* str;
+
+ MbQ = &(video->mblock[mbNum]); // current Mb
+
+
+ // If filter is disabled, return
+ if (video->sliceHdr->disable_deblocking_filter_idc == 1) return;
+
+ if (video->sliceHdr->disable_deblocking_filter_idc == 2)
+ {
+ // don't filter at slice boundaries
+ filterLeftMbEdgeFlag = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - 1, mbNum);
+ filterTopMbEdgeFlag = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - video->PicWidthInMbs, mbNum);
+ }
+
+ /* NOTE: edge=0 and edge=1~3 are separate cases because of the difference of MbP, index A and indexB calculation */
+ /* for edge = 1~3, MbP, indexA and indexB remain the same, and thus there is no need to re-calculate them for each edge */
+
+ qp_clip_tab = (int *)QP_CLIP_TAB + 12;
+
+ /* 1.VERTICAL EDGE + MB BOUNDARY (edge = 0) */
+ if (filterLeftMbEdgeFlag)
+ {
+ MbP = MbQ - 1;
+ //GetStrength(video, Strength, MbP, MbQ, 0, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ GetStrength_Edge0(Strength, MbP, MbQ, 0);
+
+ str = (void*)Strength; //de-ref type-punned pointer fix
+ if (*((uint32*)str)) // only if one of the 4 Strength bytes is != 0
+ {
+ QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
+ indexA = QP + video->FilterOffsetA;
+ indexB = QP + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *) CLIP_TAB[indexA];
+
+ if (Alpha > 0 && Beta > 0)
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_vertical(SrcY, Strength, Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_vertical(SrcY, Strength, Alpha, Beta, clipTable, pitch);
+#endif
+
+ QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
+ indexA = QPC + video->FilterOffsetA;
+ indexB = QPC + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *) CLIP_TAB[indexA];
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, 12);
+ EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, 12);
+#else
+ EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
+ EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
+#endif
+ }
+ }
+
+ } /* end of: if(filterLeftMbEdgeFlag) */
+
+ /* 2.VERTICAL EDGE (no boundary), the edges are all inside a MB */
+ /* First calculate the necesary parameters all at once, outside the loop */
+ MbP = MbQ;
+
+ indexA = MbQ->QPy + video->FilterOffsetA;
+ indexB = MbQ->QPy + video->FilterOffsetB;
+ // index
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+
+ /* Save Alpha, Beta and clipTable for future use, with the obselete variables filterLeftMbEdgeFlag, mbNum amd tmp */
+ filterLeftMbEdgeFlag = Alpha;
+ mbNum = Beta;
+ tmp = (int)clipTable;
+
+ indexA = MbQ->QPc + video->FilterOffsetA;
+ indexB = MbQ->QPc + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha_c = ALPHA_TABLE[indexA];
+ Beta_c = BETA_TABLE[indexB];
+ clipTable_c = (int *)CLIP_TAB[indexA];
+
+ GetStrength_VerticalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+
+ for (edge = 1; edge < 4; edge++) // 4 vertical strips of 16 pel
+ {
+ //GetStrength_VerticalEdges(video, Strength, MbP, MbQ, 0, edge); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ if (*((int*)(Strength + (edge << 2)))) // only if one of the 4 Strength bytes is != 0
+ {
+ if (Alpha > 0 && Beta > 0)
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2), Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2), Alpha, Beta, clipTable, pitch);
+#endif
+
+ if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+ EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+#else
+ EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+ EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+#endif
+ }
+ }
+
+ } //end edge
+
+
+
+ /* 3.HORIZONTAL EDGE + MB BOUNDARY (edge = 0) */
+ if (filterTopMbEdgeFlag)
+ {
+ MbP = MbQ - video->PicWidthInMbs;
+ //GetStrength(video, Strength, MbP, MbQ, 1, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ GetStrength_Edge0(Strength, MbP, MbQ, 1);
+ str = (void*)Strength; //de-ref type-punned pointer fix
+ if (*((uint32*)str)) // only if one of the 4 Strength bytes is != 0
+ {
+ QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
+ indexA = QP + video->FilterOffsetA;
+ indexB = QP + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_horizontal(SrcY, Strength, Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_horizontal(SrcY, Strength, Alpha, Beta, clipTable, pitch);
+#endif
+ }
+
+ QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
+ indexA = QPC + video->FilterOffsetA;
+ indexB = QPC + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, 12);
+ EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, 12);
+#else
+ EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
+ EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
+#endif
+ }
+ }
+
+ } /* end of: if(filterTopMbEdgeFlag) */
+
+
+ /* 4.HORIZONTAL EDGE (no boundary), the edges are inside a MB */
+ MbP = MbQ;
+
+ /* Recover Alpha, Beta and clipTable for edge!=0 with the variables filterLeftMbEdgeFlag, mbNum and tmp */
+ /* Note that Alpha_c, Beta_c and clipTable_c for chroma is already calculated */
+ Alpha = filterLeftMbEdgeFlag;
+ Beta = mbNum;
+ clipTable = (int *)tmp;
+
+ GetStrength_HorizontalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+
+ for (edge = 1; edge < 4; edge++) // 4 horicontal strips of 16 pel
+ {
+ //GetStrength(video, Strength, MbP, MbQ, 1, edge); // Strength for 4 blks in 1 stripe 1 => horizontal edge
+ if (*((int*)(Strength + (edge << 2)))) // only if one of the 4 Strength bytes is != 0
+ {
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*20, Strength + (edge << 2), Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*pitch, Strength + (edge << 2), Alpha, Beta, clipTable, pitch);
+#endif
+ }
+
+ if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+ EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+#else
+ EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+ EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+#endif
+ }
+ }
+
+ } //end edge
+
+ return;
+}
+
+/*
+ *****************************************************************************************************
+ * \brief returns a buffer of 4 Strength values for one stripe in a mb (for different Frame types)
+ *****************************************************************************************************
+*/
+
+void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir)
+{
+ int tmp;
+ int16 *ptrQ, *ptrP;
+ void* vptr;
+ uint8 *pStrength;
+ void* refIdx;
+
+ if (MbP->mbMode == AVC_I4 || MbP->mbMode == AVC_I16 ||
+ MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+
+ *((int*)Strength) = ININT_STRENGTH[0]; // Start with Strength=3. or Strength=4 for Mb-edge
+
+ }
+ else // if not intra or SP-frame
+ {
+ *((int*)Strength) = 0;
+
+ if (dir == 0) // Vertical Edge 0
+ {
+
+ //1. Check the ref_frame_id
+ refIdx = (void*) MbQ->RefIdx; //de-ref type-punned pointer fix
+ ptrQ = (int16*)refIdx;
+ refIdx = (void*)MbP->RefIdx; //de-ref type-punned pointer fix
+ ptrP = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptrQ[0] != ptrP[1]) pStrength[0] = 1;
+ if (ptrQ[2] != ptrP[3]) pStrength[2] = 1;
+ pStrength[1] = pStrength[0];
+ pStrength[3] = pStrength[2];
+
+ //2. Check the non-zero coeff blocks (4x4)
+ if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[3] != 0) pStrength[0] = 2;
+ if (MbQ->nz_coeff[4] != 0 || MbP->nz_coeff[7] != 0) pStrength[1] = 2;
+ if (MbQ->nz_coeff[8] != 0 || MbP->nz_coeff[11] != 0) pStrength[2] = 2;
+ if (MbQ->nz_coeff[12] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
+
+ //3. Only need to check the mv difference
+ vptr = (void*)MbQ->mvL0; // for deref type-punned pointer
+ ptrQ = (int16*)vptr;
+ ptrP = (int16*)(MbP->mvL0 + 3); // points to 4x4 block #3 (the 4th column)
+
+ // 1st blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 2nd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 3rd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 4th blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+ }
+ else // Horizontal Edge 0
+ {
+
+ //1. Check the ref_frame_id
+ refIdx = (void*)MbQ->RefIdx; //de-ref type-punned pointer
+ ptrQ = (int16*)refIdx;
+ refIdx = (void*)MbP->RefIdx; //de-ref type-punned pointer
+ ptrP = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptrQ[0] != ptrP[2]) pStrength[0] = 1;
+ if (ptrQ[1] != ptrP[3]) pStrength[2] = 1;
+ pStrength[1] = pStrength[0];
+ pStrength[3] = pStrength[2];
+
+ //2. Check the non-zero coeff blocks (4x4)
+ if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[12] != 0) pStrength[0] = 2;
+ if (MbQ->nz_coeff[1] != 0 || MbP->nz_coeff[13] != 0) pStrength[1] = 2;
+ if (MbQ->nz_coeff[2] != 0 || MbP->nz_coeff[14] != 0) pStrength[2] = 2;
+ if (MbQ->nz_coeff[3] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
+
+ //3. Only need to check the mv difference
+ vptr = (void*)MbQ->mvL0;
+ ptrQ = (int16*)vptr;
+ ptrP = (int16*)(MbP->mvL0 + 12); // points to 4x4 block #12 (the 4th row)
+
+ // 1st blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 2nd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 3rd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 4th blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ } /* end of: else if(dir == 0) */
+
+ } /* end of: if( !(MbP->mbMode == AVC_I4 ...) */
+}
+
+
+void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ)
+{
+ int idx, tmp;
+ int16 *ptr, *pmvx, *pmvy;
+ uint8 *pnz;
+ uint8 *pStrength, *pStr;
+ void* refIdx;
+
+ if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+ *((int*)Strength) = ININT_STRENGTH[1]; // Start with Strength=3. or Strength=4 for Mb-edge
+ *((int*)(Strength + 4)) = ININT_STRENGTH[2];
+ *((int*)(Strength + 8)) = ININT_STRENGTH[3];
+ }
+ else // Not intra or SP-frame
+ {
+
+ *((int*)Strength) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 4)) = 0;
+ *((int*)(Strength + 8)) = 0;
+
+ //1. Check the ref_frame_id
+ refIdx = (void*)MbQ->RefIdx; //de-ref type-punned pointer fix
+ ptr = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptr[0] != ptr[1]) pStrength[4] = 1;
+ if (ptr[2] != ptr[3]) pStrength[6] = 1;
+ pStrength[5] = pStrength[4];
+ pStrength[7] = pStrength[6];
+
+ //2. Check the nz_coeff block and mv difference
+ pmvx = (int16*)(MbQ->mvL0 + 1); // points to 4x4 block #1,not #0
+ pmvy = pmvx + 1;
+ for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
+ {
+ // first/third row : 1,2,3 or 9,10,12
+ // Strength = 2 for a whole row
+ pnz = MbQ->nz_coeff + (idx << 2);
+ if (*pnz++ != 0) *pStrength = 2;
+ if (*pnz++ != 0)
+ {
+ *pStrength = 2;
+ *(pStrength + 4) = 2;
+ }
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 4) = 2;
+ *(pStrength + 8) = 2;
+ }
+ if (*pnz != 0) *(pStrength + 8) = 2;
+
+ // Then Strength = 1
+ if (*pStrength == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 4;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 8;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // Second/fourth row: 5,6,7 or 14,15,16
+ // Strength = 2 for a whole row
+ pnz = MbQ->nz_coeff + ((idx + 1) << 2);
+ if (*pnz++ != 0) *(pStrength + 1) = 2;
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 1) = 2;
+ *(pStrength + 5) = 2;
+ }
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 5) = 2;
+ *(pStrength + 9) = 2;
+ }
+ if (*pnz != 0) *(pStrength + 9) = 2;
+
+ // Then Strength = 1
+ pmvx += 4;
+ pmvy += 4;
+ pStr = pStrength + 1;
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 5;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 9;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // update some variables for the next two rows
+ pmvx += 4;
+ pmvy += 4;
+ pStrength += 2;
+
+ } /* end of: for(idx=0; idx<2; idx++) */
+
+ } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
+}
+
+
+void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ)
+{
+ int idx, tmp;
+ int16 *ptr, *pmvx, *pmvy;
+ uint8 *pStrength, *pStr;
+ void* refIdx;
+
+ if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+ *((int*)Strength) = ININT_STRENGTH[1]; // Start with Strength=3. or Strength=4 for Mb-edge
+ *((int*)(Strength + 4)) = ININT_STRENGTH[2];
+ *((int*)(Strength + 8)) = ININT_STRENGTH[3];
+ }
+ else // Not intra or SP-frame
+ {
+
+ *((int*)Strength) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 4)) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 8)) = 0; // for non-intra MB, strength = 0, 1 or 2.
+
+
+ //1. Check the ref_frame_id
+ refIdx = (void*) MbQ->RefIdx; // de-ref type-punned fix
+ ptr = (int16*) refIdx;
+ pStrength = Strength;
+ if (ptr[0] != ptr[2]) pStrength[4] = 1;
+ if (ptr[1] != ptr[3]) pStrength[6] = 1;
+ pStrength[5] = pStrength[4];
+ pStrength[7] = pStrength[6];
+
+ //2. Check the nz_coeff block and mv difference
+ pmvx = (int16*)(MbQ->mvL0 + 4); // points to 4x4 block #4,not #0
+ pmvy = pmvx + 1;
+ for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
+ {
+ // first/third row : 1,2,3 or 9,10,12
+ // Strength = 2 for a whole row
+ if (MbQ->nz_coeff[idx] != 0) *pStrength = 2;
+ if (MbQ->nz_coeff[4+idx] != 0)
+ {
+ *pStrength = 2;
+ *(pStrength + 4) = 2;
+ }
+ if (MbQ->nz_coeff[8+idx] != 0)
+ {
+ *(pStrength + 4) = 2;
+ *(pStrength + 8) = 2;
+ }
+ if (MbQ->nz_coeff[12+idx] != 0) *(pStrength + 8) = 2;
+
+ // Then Strength = 1
+ if (*pStrength == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 4;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 8;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // Second/fourth row: 5,6,7 or 14,15,16
+ // Strength = 2 for a whole row
+ if (MbQ->nz_coeff[idx+1] != 0) *(pStrength + 1) = 2;
+ if (MbQ->nz_coeff[4+idx+1] != 0)
+ {
+ *(pStrength + 1) = 2;
+ *(pStrength + 5) = 2;
+ }
+ if (MbQ->nz_coeff[8+idx+1] != 0)
+ {
+ *(pStrength + 5) = 2;
+ *(pStrength + 9) = 2;
+ }
+ if (MbQ->nz_coeff[12+idx+1] != 0) *(pStrength + 9) = 2;
+
+ // Then Strength = 1
+ pmvx -= 14;
+ pmvy -= 14; // -14 = -16 + 2
+ pStr = pStrength + 1;
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 5;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 9;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // update some variables for the next two rows
+ pmvx -= 14;
+ pmvy -= 14; // -14 = -16 + 2
+ pStrength += 2;
+
+ } /* end of: for(idx=0; idx<2; idx++) */
+
+ } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
+}
+
+/*
+ *****************************************************************************************
+ * \brief Filters one edge of 16 (luma) or 8 (chroma) pel
+ *****************************************************************************************
+*/
+
+void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, ap = 0, aq = 0, Strng;
+ int C0, c0, dif, AbsDelta, tmp, tmp1;
+ int L2 = 0, L1, L0, R0, R1, R2 = 0, RL0;
+
+
+ if (Strength[0] == 4) /* INTRA strong filtering */
+ {
+ for (pel = 0; pel < 16; pel++)
+ {
+ R0 = SrcPtr[0];
+ R1 = SrcPtr[pitch];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)];
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ AbsDelta = R0 - L0;
+ if (AbsDelta < 0) AbsDelta = -AbsDelta;
+ tmp &= (AbsDelta - Alpha);
+
+ if (tmp < 0)
+ {
+ AbsDelta -= ((Alpha >> 2) + 2);
+ R2 = SrcPtr[pitch<<1]; //inc2
+ L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
+
+ // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = AbsDelta & (tmp - Beta);
+
+ // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = AbsDelta & (tmp - Beta);
+
+ if (aq < 0)
+ {
+ tmp = R1 + R0 + L0;
+ SrcPtr[0] = (L1 + (tmp << 1) + R2 + 4) >> 3;
+ tmp += R2;
+ SrcPtr[pitch] = (tmp + 2) >> 2;
+ SrcPtr[pitch<<1] = (((SrcPtr[(pitch+(pitch<<1))] + R2) << 1) + tmp + 4) >> 3;
+ }
+ else
+ SrcPtr[0] = ((R1 << 1) + R0 + L1 + 2) >> 2;
+
+ if (ap < 0)
+ {
+ tmp = L1 + R0 + L0;
+ SrcPtr[-pitch] = (R1 + (tmp << 1) + L2 + 4) >> 3;
+ tmp += L2;
+ SrcPtr[-(pitch<<1)] = (tmp + 2) >> 2;
+ SrcPtr[-(pitch+(pitch<<1))] = (((SrcPtr[-(pitch<<2)] + L2) << 1) + tmp + 4) >> 3;
+ }
+ else
+ SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
+
+ } /* if(tmp < 0) */
+
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+
+ } /* if(Strength[0] == 4) */
+
+ else /* Normal filtering */
+ {
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel >> 2];
+ if (Strng)
+ {
+ R0 = SrcPtr[0];
+ R1 = SrcPtr[pitch];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)]; // inc2
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Alpha);
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ if (tmp < 0)
+ {
+ R2 = SrcPtr[pitch<<1]; //inc2
+ L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
+
+ // |R0 - R2| < Beta
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = tmp - Beta;
+
+ // |L0 - L2| < Beta
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = tmp - Beta;
+
+
+ c0 = C0 = clipTable[Strng];
+ if (ap < 0) c0++;
+ if (aq < 0) c0++;
+
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ RL0 = R0 + L0;
+ R0 -= dif;
+ L0 += dif;
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ SrcPtr[-pitch] = L0;
+ SrcPtr[0] = R0;
+
+ if (C0 != 0) /* Multiple zeros in the clip tables */
+ {
+ if (aq < 0) // SrcPtr[inc] += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
+ {
+ R2 = (R2 + ((RL0 + 1) >> 1) - (R1 << 1)) >> 1;
+ tmp = R2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ R2 = (tmp & (C0 << 1)) - C0;
+ }
+ SrcPtr[pitch] += R2;
+ }
+
+ if (ap < 0) //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
+ {
+ L2 = (L2 + ((RL0 + 1) >> 1) - (L1 << 1)) >> 1;
+ tmp = L2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ L2 = (tmp & (C0 << 1)) - C0;
+ }
+ SrcPtr[-(pitch<<1)] += L2;
+ }
+ }
+
+ } /* if(tmp < 0) */
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* for(pel=0; pel<16; pel++) */
+
+ } /* else if(Strength[0] == 4) */
+}
+
+void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, ap = 1, aq = 1;
+ int C0, c0, dif, AbsDelta, Strng, tmp, tmp1;
+ int L2 = 0, L1, L0, R0, R1, R2 = 0;
+ uint8 *ptr, *ptr1;
+ register uint R_in, L_in;
+ uint R_out, L_out;
+
+
+ if (Strength[0] == 4) /* INTRA strong filtering */
+ {
+
+ for (pel = 0; pel < 16; pel++)
+ {
+
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ // |R0 - R1| < Beta
+ tmp1 = (R_in & 0xff) - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+
+ //|L0 - L1| < Beta
+ tmp1 = (L_in >> 24) - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ AbsDelta = (R_in & 0xff) - (L_in >> 24);
+ if (AbsDelta < 0) AbsDelta = -AbsDelta;
+ tmp &= (AbsDelta - Alpha);
+
+ if (tmp < 0)
+ {
+ AbsDelta -= ((Alpha >> 2) + 2);
+ R2 = (R_in >> 16) & 0xff;
+ L2 = (L_in >> 8) & 0xff;
+
+ // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp1 = (R_in & 0xff) - R2;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ aq = AbsDelta & (tmp1 - Beta);
+
+ // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp1 = (L_in >> 24) - L2;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ ap = AbsDelta & (tmp1 - Beta);
+
+
+ ptr = SrcPtr;
+ if (aq < 0)
+ {
+ R_out = (R_in >> 24) << 24; // Keep R3 at the fourth byte
+
+ tmp = R0 + L0 + R1;
+ R_out |= (((tmp << 1) + L1 + R2 + 4) >> 3);
+ tmp += R2;
+ R_out |= (((tmp + 2) >> 2) << 8);
+ tmp1 = ((R_in >> 24) + R2) << 1;
+ R_out |= (((tmp1 + tmp + 4) >> 3) << 16);
+
+ *((uint *)SrcPtr) = R_out;
+ }
+ else
+ *ptr = ((R1 << 1) + R0 + L1 + 2) >> 2;
+
+
+ if (ap < 0)
+ {
+ L_out = (L_in << 24) >> 24; // Keep L3 at the first byte
+
+ tmp = R0 + L0 + L1;
+ L_out |= ((((tmp << 1) + R1 + L2 + 4) >> 3) << 24);
+ tmp += L2;
+ L_out |= (((tmp + 2) >> 2) << 16);
+ tmp1 = ((L_in & 0xff) + L2) << 1;
+ L_out |= (((tmp1 + tmp + 4) >> 3) << 8);
+
+ *((uint *)(SrcPtr - 4)) = L_out;
+ }
+ else
+ *(--ptr) = ((L1 << 1) + L0 + R1 + 2) >> 2;
+
+ } /* if(tmp < 0) */
+
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+
+ } /* if(Strength[0] == 4) */
+
+ else /* Normal filtering */
+ {
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel >> 2];
+ if (Strng)
+ {
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ //|R0 - L0| < Alpha
+ tmp = R0 - L0;
+ if (tmp < 0) tmp = -tmp;
+ tmp -= Alpha;
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ if (tmp < 0)
+ {
+ L2 = SrcPtr[-3];
+ R2 = SrcPtr[2];
+
+ // |R0 - R2| < Beta
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = tmp - Beta;
+
+ // |L0 - L2| < Beta
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = tmp - Beta;
+
+
+ c0 = C0 = clipTable[Strng];
+ if (ap < 0) c0++;
+ if (aq < 0) c0++;
+
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ ptr = SrcPtr;
+ ptr1 = SrcPtr - 1;
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ R_in = R0 - dif;
+ L_in = L0 + dif; /* cannot re-use R0 and L0 here */
+ if ((uint)R_in > 255)
+ {
+ tmp = ~((int)R_in >> 31);
+ R_in = tmp & 255;
+ }
+ if ((uint)L_in > 255)
+ {
+ tmp = ~((int)L_in >> 31);
+ L_in = tmp & 255;
+ }
+ *ptr1-- = L_in;
+ *ptr++ = R_in;
+
+ if (C0 != 0) // Multiple zeros in the clip tables
+ {
+ if (ap < 0) //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
+ {
+ L2 = (L2 + ((R0 + L0 + 1) >> 1) - (L1 << 1)) >> 1;
+ tmp = L2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ L2 = (tmp & (C0 << 1)) - C0;
+ }
+ *ptr1 += L2;
+ }
+
+ if (aq < 0) // SrcPtr[inc] += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
+ {
+ R2 = (R2 + ((R0 + L0 + 1) >> 1) - (R1 << 1)) >> 1;
+ tmp = R2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ R2 = (tmp & (C0 << 1)) - C0;
+ }
+ *ptr += R2;
+ }
+ }
+
+ } /* if(tmp < 0) */
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* for(pel=0; pel<16; pel++) */
+
+ } /* else if(Strength[0] == 4) */
+
+}
+
+void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, Strng;
+ int c0, dif;
+ int L1, L0, R0, R1, tmp, tmp1;
+ uint8 *ptr;
+ uint R_in, L_in;
+
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel>>2];
+ if (Strng)
+ {
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Alpha);
+
+ if (tmp < 0)
+ {
+ ptr = SrcPtr;
+ if (Strng == 4) /* INTRA strong filtering */
+ {
+ *ptr-- = ((R1 << 1) + R0 + L1 + 2) >> 2;
+ *ptr = ((L1 << 1) + L0 + R1 + 2) >> 2;
+ }
+ else /* normal filtering */
+ {
+ c0 = clipTable[Strng] + 1;
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ L0 += dif;
+ R0 -= dif;
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+
+ *ptr-- = R0;
+ *ptr = L0;
+ }
+ }
+ pel ++;
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+ else
+ {
+ pel += 3;
+ SrcPtr += (pitch << 1); //PtrInc << 1;
+ }
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+}
+
+
+void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, Strng;
+ int c0, dif;
+ int L1, L0, R0, R1, tmp, tmp1;
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel>>2];
+ if (Strng)
+ {
+ R0 = SrcPtr[0];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)]; //inc2
+ R1 = SrcPtr[pitch];
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Alpha);
+
+ if (tmp < 0)
+ {
+ if (Strng == 4) /* INTRA strong filtering */
+ {
+ SrcPtr[0] = ((R1 << 1) + R0 + L1 + 2) >> 2;
+ SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
+ }
+ else /* normal filtering */
+ {
+ c0 = clipTable[Strng] + 1;
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ L0 += dif;
+ R0 -= dif;
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+ SrcPtr[0] = R0;
+ SrcPtr[-pitch] = L0;
+ }
+ }
+
+ pel ++;
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+ else
+ {
+ pel += 3;
+ SrcPtr += 2;
+ }
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/dpb.cpp b/media/libstagefright/codecs/avc/common/src/dpb.cpp
new file mode 100644
index 0000000..2c4c7da
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/dpb.cpp
@@ -0,0 +1,724 @@
+/* ------------------------------------------------------------------
+ * 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"
+
+#define DPB_MEM_ATTR 0
+
+AVCStatus InitDPB(AVCHandle *avcHandle, AVCCommonObj *video, int FrameHeightInMbs, int PicWidthInMbs, bool padding)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int level, framesize, num_fs;
+ void *userData = avcHandle->userData;
+#ifndef PV_MEMORY_POOL
+ uint32 addr;
+#endif
+ uint16 refIdx = 0;
+ level = video->currSeqParams->level_idc;
+
+ for (num_fs = 0; num_fs < MAX_FS; num_fs++)
+ {
+ dpb->fs[num_fs] = NULL;
+ }
+
+ framesize = (int)(((FrameHeightInMbs * PicWidthInMbs) << 7) * 3);
+ if (padding)
+ {
+ video->padded_size = (int)((((FrameHeightInMbs + 2) * (PicWidthInMbs + 2)) << 7) * 3) - framesize;
+ }
+ else
+ {
+ video->padded_size = 0;
+ }
+
+#ifndef PV_MEMORY_POOL
+ if (dpb->decoded_picture_buffer)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer);
+ dpb->decoded_picture_buffer = NULL;
+ }
+#endif
+ /* need to allocate one extra frame for current frame, DPB only defines for reference frames */
+
+ dpb->num_fs = (uint32)(MaxDPBX2[mapLev2Idx[level]] << 2) / (3 * FrameHeightInMbs * PicWidthInMbs) + 1;
+ if (dpb->num_fs > MAX_FS)
+ {
+ dpb->num_fs = MAX_FS;
+ }
+
+ if (video->currSeqParams->num_ref_frames + 1 > (uint32)dpb->num_fs)
+ {
+ dpb->num_fs = video->currSeqParams->num_ref_frames + 1;
+ }
+
+ dpb->dpb_size = dpb->num_fs * (framesize + video->padded_size);
+// dpb->dpb_size = (uint32)MaxDPBX2[mapLev2Idx[level]]*512 + framesize;
+
+#ifndef PV_MEMORY_POOL
+ dpb->decoded_picture_buffer = (uint8*) avcHandle->CBAVC_Malloc(userData, dpb->dpb_size, 100/*DPB_MEM_ATTR*/);
+
+ if (dpb->decoded_picture_buffer == NULL || dpb->decoded_picture_buffer&0x3) // not word aligned
+ return AVC_MEMORY_FAIL;
+#endif
+ dpb->used_size = 0;
+ num_fs = 0;
+
+ while (num_fs < dpb->num_fs)
+ {
+ /* fs is an array pointers to AVCDecPicture */
+ dpb->fs[num_fs] = (AVCFrameStore*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCFrameStore), 101/*DEFAULT_ATTR*/);
+ if (dpb->fs[num_fs] == NULL)
+ {
+ return AVC_MEMORY_FAIL;
+ }
+#ifndef PV_MEMORY_POOL
+ /* assign the actual memory for Sl, Scb, Scr */
+ dpb->fs[num_fs]->base_dpb = dpb->decoded_picture_buffer + dpb->used_size;
+#endif
+ dpb->fs[num_fs]->IsReference = 0;
+ dpb->fs[num_fs]->IsLongTerm = 0;
+ dpb->fs[num_fs]->IsOutputted = 3;
+ dpb->fs[num_fs]->frame.RefIdx = refIdx++; /* this value will remain unchanged through out the encoding session */
+ dpb->fs[num_fs]->frame.picType = AVC_FRAME;
+ dpb->fs[num_fs]->frame.isLongTerm = 0;
+ dpb->fs[num_fs]->frame.isReference = 0;
+ video->RefPicList0[num_fs] = &(dpb->fs[num_fs]->frame);
+ dpb->fs[num_fs]->frame.padded = 0;
+ dpb->used_size += (framesize + video->padded_size);
+ num_fs++;
+ }
+
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus AVCConfigureSequence(AVCHandle *avcHandle, AVCCommonObj *video, bool padding)
+{
+ void *userData = avcHandle->userData;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int framesize, ii; /* size of one frame */
+ uint PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs, PicSizeInMapUnits;
+ uint num_fs;
+ /* derived variables from SPS */
+ PicWidthInMbs = video->currSeqParams->pic_width_in_mbs_minus1 + 1;
+ PicHeightInMapUnits = video->currSeqParams->pic_height_in_map_units_minus1 + 1 ;
+ FrameHeightInMbs = (2 - video->currSeqParams->frame_mbs_only_flag) * PicHeightInMapUnits ;
+ PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits ;
+
+ if (video->PicSizeInMapUnits != PicSizeInMapUnits || video->currSeqParams->level_idc != video->level_idc)
+ {
+ /* make sure you mark all the frames as unused for reference for flushing*/
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ dpb->fs[ii]->IsReference = 0;
+ dpb->fs[ii]->IsOutputted |= 0x02;
+ }
+
+ num_fs = (uint32)(MaxDPBX2[(uint32)mapLev2Idx[video->currSeqParams->level_idc]] << 2) / (3 * PicSizeInMapUnits) + 1;
+ if (num_fs >= MAX_FS)
+ {
+ num_fs = MAX_FS;
+ }
+#ifdef PV_MEMORY_POOL
+ if (padding)
+ {
+ avcHandle->CBAVC_DPBAlloc(avcHandle->userData,
+ PicSizeInMapUnits + ((PicWidthInMbs + 2) << 1) + (PicHeightInMapUnits << 1), num_fs);
+ }
+ else
+ {
+ avcHandle->CBAVC_DPBAlloc(avcHandle->userData, PicSizeInMapUnits, num_fs);
+ }
+#endif
+ CleanUpDPB(avcHandle, video);
+ if (InitDPB(avcHandle, video, FrameHeightInMbs, PicWidthInMbs, padding) != AVC_SUCCESS)
+ {
+ return AVC_FAIL;
+ }
+ /* Allocate video->mblock upto PicSizeInMbs and populate the structure such as the neighboring MB pointers. */
+ framesize = (FrameHeightInMbs * PicWidthInMbs);
+ if (video->mblock)
+ {
+ avcHandle->CBAVC_Free(userData, (uint32)video->mblock);
+ video->mblock = NULL;
+ }
+ video->mblock = (AVCMacroblock*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMacroblock) * framesize, DEFAULT_ATTR);
+ if (video->mblock == NULL)
+ {
+ return AVC_FAIL;
+ }
+ for (ii = 0; ii < framesize; ii++)
+ {
+ video->mblock[ii].slice_id = -1;
+ }
+ /* Allocate memory for intra prediction */
+#ifdef MB_BASED_DEBLOCK
+ video->intra_pred_top = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 4, FAST_MEM_ATTR);
+ if (video->intra_pred_top == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->intra_pred_top_cb = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR);
+ if (video->intra_pred_top_cb == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->intra_pred_top_cr = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR);
+ if (video->intra_pred_top_cr == NULL)
+ {
+ return AVC_FAIL;
+ }
+
+#endif
+ /* Allocate slice group MAP map */
+
+ if (video->MbToSliceGroupMap)
+ {
+ avcHandle->CBAVC_Free(userData, (uint32)video->MbToSliceGroupMap);
+ video->MbToSliceGroupMap = NULL;
+ }
+ video->MbToSliceGroupMap = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(uint) * PicSizeInMapUnits * 2, 7/*DEFAULT_ATTR*/);
+ if (video->MbToSliceGroupMap == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->PicSizeInMapUnits = PicSizeInMapUnits;
+ video->level_idc = video->currSeqParams->level_idc;
+
+ }
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus CleanUpDPB(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii;
+ void *userData = avcHandle->userData;
+
+ for (ii = 0; ii < MAX_FS; ii++)
+ {
+ if (dpb->fs[ii] != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->fs[ii]);
+ dpb->fs[ii] = NULL;
+ }
+ }
+#ifndef PV_MEMORY_POOL
+ if (dpb->decoded_picture_buffer)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer);
+ dpb->decoded_picture_buffer = NULL;
+ }
+#endif
+ dpb->used_size = 0;
+ dpb->dpb_size = 0;
+
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus DPBInitBuffer(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii, status;
+
+ /* Before doing any decoding, check if there's a frame memory available */
+ /* look for next unused dpb->fs, or complementary field pair */
+ /* video->currPic is assigned to this */
+
+ /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ /* looking for the one not used or not reference and has been outputted */
+ if (dpb->fs[ii]->IsReference == 0 && dpb->fs[ii]->IsOutputted == 3)
+ {
+ video->currFS = dpb->fs[ii];
+#ifdef PV_MEMORY_POOL
+ status = avcHandle->CBAVC_FrameBind(avcHandle->userData, ii, &(video->currFS->base_dpb));
+ if (status == AVC_FAIL)
+ {
+ return AVC_NO_BUFFER; /* this should not happen */
+ }
+#endif
+ break;
+ }
+ }
+ if (ii == dpb->num_fs)
+ {
+ return AVC_PICTURE_OUTPUT_READY; /* no empty frame available */
+ }
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF void DPBInitPic(AVCCommonObj *video, int CurrPicNum)
+{
+ int offset = 0;
+ int offsetc = 0;
+ int luma_framesize;
+ /* this part has to be set here, assuming that slice header and POC have been decoded. */
+ /* used in GetOutput API */
+ video->currFS->PicOrderCnt = video->PicOrderCnt;
+ video->currFS->FrameNum = video->sliceHdr->frame_num;
+ video->currFS->FrameNumWrap = CurrPicNum; // MC_FIX
+ /* initialize everything to zero */
+ video->currFS->IsOutputted = 0;
+ video->currFS->IsReference = 0;
+ video->currFS->IsLongTerm = 0;
+ video->currFS->frame.isReference = FALSE;
+ video->currFS->frame.isLongTerm = FALSE;
+
+ /* initialize the pixel pointer to NULL */
+ video->currFS->frame.Sl = video->currFS->frame.Scb = video->currFS->frame.Scr = NULL;
+
+ /* determine video->currPic */
+ /* assign dbp->base_dpb to fs[i]->frame.Sl, Scb, Scr .*/
+ /* For PicSizeInMbs, see DecodeSliceHeader() */
+
+ video->currPic = &(video->currFS->frame);
+
+ video->currPic->padded = 0; // reset this flag to not-padded
+
+ if (video->padded_size)
+ {
+ offset = ((video->PicWidthInSamplesL + 32) << 4) + 16; // offset to the origin
+ offsetc = (offset >> 2) + 4;
+ luma_framesize = (int)((((video->FrameHeightInMbs + 2) * (video->PicWidthInMbs + 2)) << 8));
+ }
+ else
+ luma_framesize = video->PicSizeInMbs << 8;
+
+
+ video->currPic->Sl = video->currFS->base_dpb + offset;
+ video->currPic->Scb = video->currFS->base_dpb + luma_framesize + offsetc;
+ video->currPic->Scr = video->currPic->Scb + (luma_framesize >> 2);
+ video->currPic->pitch = video->PicWidthInSamplesL + (video->padded_size == 0 ? 0 : 32);
+
+
+ video->currPic->height = video->PicHeightInSamplesL;
+ video->currPic->width = video->PicWidthInSamplesL;
+ video->currPic->PicNum = CurrPicNum;
+}
+
+/* to release skipped frame after encoding */
+OSCL_EXPORT_REF void DPBReleaseCurrentFrame(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii;
+
+ video->currFS->IsOutputted = 3; // return this buffer.
+
+#ifdef PV_MEMORY_POOL /* for non-memory pool, no need to do anything */
+
+ /* search for current frame index */
+ ii = dpb->num_fs;
+ while (ii--)
+ {
+ if (dpb->fs[ii] == video->currFS)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+ break;
+ }
+ }
+#endif
+
+ return ;
+}
+
+/* see subclause 8.2.5.1 */
+OSCL_EXPORT_REF AVCStatus StorePictureInDPB(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCStatus status;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ int ii, num_ref;
+
+ /* number 1 of 8.2.5.1, we handle gaps in frame_num differently without using the memory */
+ /* to be done!!!! */
+
+ /* number 3 of 8.2.5.1 */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* not current frame */
+ {
+ dpb->fs[ii]->IsReference = 0; /* mark as unused for reference */
+ dpb->fs[ii]->IsLongTerm = 0; /* but still used until output */
+ dpb->fs[ii]->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (dpb->fs[ii]->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+ }
+#endif
+ }
+ }
+
+ video->currPic->isReference = TRUE;
+ video->currFS->IsReference = 3;
+
+ if (sliceHdr->long_term_reference_flag == 0)
+ {
+ video->currPic->isLongTerm = FALSE;
+ video->currFS->IsLongTerm = 0;
+ video->MaxLongTermFrameIdx = -1;
+ }
+ else
+ {
+ video->currPic->isLongTerm = TRUE;
+ video->currFS->IsLongTerm = 3;
+ video->currFS->LongTermFrameIdx = 0;
+ video->MaxLongTermFrameIdx = 0;
+ }
+ if (sliceHdr->no_output_of_prior_pics_flag)
+ {
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* not current frame */
+ {
+ dpb->fs[ii]->IsOutputted = 3;
+#ifdef PV_MEMORY_POOL
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+#endif
+ }
+ }
+ }
+ video->mem_mgr_ctrl_eq_5 = TRUE; /* flush reference frames MC_FIX */
+ }
+ else
+ {
+ if (video->currPic->isReference == TRUE)
+ {
+ if (sliceHdr->adaptive_ref_pic_marking_mode_flag == 0)
+ {
+ status = sliding_window_process(avcHandle, video, dpb); /* we may have to do this after adaptive_memory_marking */
+ }
+ else
+ {
+ status = adaptive_memory_marking(avcHandle, video, dpb, sliceHdr);
+ }
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ /* number 4 of 8.2.5.1 */
+ /* This basically says every frame must be at least used for short-term ref. */
+ /* Need to be revisited!!! */
+ /* look at insert_picture_in_dpb() */
+
+
+
+ if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currPic->isLongTerm == FALSE)
+ {
+ if (video->currPic->isReference)
+ {
+ video->currFS->IsReference = 3;
+ }
+ else
+ {
+ video->currFS->IsReference = 0;
+ }
+ video->currFS->IsLongTerm = 0;
+ }
+
+ /* check if number of reference frames doesn't exceed num_ref_frames */
+ num_ref = 0;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference)
+ {
+ num_ref++;
+ }
+ }
+
+ if (num_ref > (int)video->currSeqParams->num_ref_frames)
+ {
+ return AVC_FAIL; /* out of range */
+ }
+
+ return AVC_SUCCESS;
+}
+
+
+AVCStatus sliding_window_process(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb)
+{
+ int ii, numShortTerm, numLongTerm;
+ int32 MinFrameNumWrap;
+ int MinIdx;
+
+
+ numShortTerm = 0;
+ numLongTerm = 0;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* do not count the current frame */
+ {
+ if (dpb->fs[ii]->IsLongTerm)
+ {
+ numLongTerm++;
+ }
+ else if (dpb->fs[ii]->IsReference)
+ {
+ numShortTerm++;
+ }
+ }
+ }
+
+ while (numShortTerm + numLongTerm >= (int)video->currSeqParams->num_ref_frames)
+ {
+ /* get short-term ref frame with smallest PicOrderCnt */
+ /* this doesn't work for all I-slice clip since PicOrderCnt will not be initialized */
+
+ MinFrameNumWrap = 0x7FFFFFFF;
+ MinIdx = -1;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference && !dpb->fs[ii]->IsLongTerm)
+ {
+ if (dpb->fs[ii]->FrameNumWrap < MinFrameNumWrap)
+ {
+ MinFrameNumWrap = dpb->fs[ii]->FrameNumWrap;
+ MinIdx = ii;
+ }
+ }
+ }
+ if (MinIdx < 0) /* something wrong, impossible */
+ {
+ return AVC_FAIL;
+ }
+
+ /* 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
+ numShortTerm--;
+ }
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.5.4 */
+AVCStatus adaptive_memory_marking(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, AVCSliceHeader *sliceHdr)
+{
+ int ii;
+
+ ii = 0;
+ while (ii < MAX_DEC_REF_PIC_MARKING && sliceHdr->memory_management_control_operation[ii] != 0)
+ {
+ switch (sliceHdr->memory_management_control_operation[ii])
+ {
+ case 1:
+ MemMgrCtrlOp1(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii]);
+ // update_ref_list(dpb);
+ break;
+ case 2:
+ MemMgrCtrlOp2(avcHandle, dpb, sliceHdr->long_term_pic_num[ii]);
+ break;
+ case 3:
+ MemMgrCtrlOp3(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii], sliceHdr->long_term_frame_idx[ii]);
+ break;
+ case 4:
+ MemMgrCtrlOp4(avcHandle, video, dpb, sliceHdr->max_long_term_frame_idx_plus1[ii]);
+ break;
+ case 5:
+ MemMgrCtrlOp5(avcHandle, video, dpb);
+ video->currFS->FrameNum = 0; //
+ video->currFS->PicOrderCnt = 0;
+ break;
+ case 6:
+ MemMgrCtrlOp6(avcHandle, video, dpb, sliceHdr->long_term_frame_idx[ii]);
+ break;
+ }
+ ii++;
+ }
+
+ if (ii == MAX_DEC_REF_PIC_MARKING)
+ {
+ return AVC_FAIL; /* exceed the limit */
+ }
+
+ return AVC_SUCCESS;
+}
+
+
+/* see subclause 8.2.5.4.1, mark short-term picture as "unused for reference" */
+void MemMgrCtrlOp1(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, int difference_of_pic_nums_minus1)
+{
+ int picNumX, ii;
+
+ picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1);
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference == 3 && dpb->fs[ii]->IsLongTerm == 0)
+ {
+ if (dpb->fs[ii]->frame.PicNum == picNumX)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ return ;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* see subclause 8.2.5.4.2 mark long-term picture as "unused for reference" */
+void MemMgrCtrlOp2(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, int long_term_pic_num)
+{
+ int ii;
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsLongTerm == 3)
+ {
+ if (dpb->fs[ii]->frame.LongTermPicNum == long_term_pic_num)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.5.4.3 assign LongTermFrameIdx to a short-term ref picture */
+void MemMgrCtrlOp3(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint difference_of_pic_nums_minus1,
+ uint long_term_frame_idx)
+{
+ int picNumX, ii;
+
+ picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1);
+
+ /* look for fs[i] with long_term_frame_idx */
+
+ unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx);
+
+
+ /* now mark the picture with picNumX to long term frame idx */
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference == 3)
+ {
+ if ((dpb->fs[ii]->frame.isLongTerm == FALSE) && (dpb->fs[ii]->frame.PicNum == picNumX))
+ {
+ dpb->fs[ii]->LongTermFrameIdx = long_term_frame_idx;
+ dpb->fs[ii]->frame.LongTermPicNum = long_term_frame_idx;
+
+ dpb->fs[ii]->frame.isLongTerm = TRUE;
+
+ dpb->fs[ii]->IsLongTerm = 3;
+ return;
+ }
+ }
+ }
+
+}
+
+/* see subclause 8.2.5.4.4, MaxLongTermFrameIdx */
+void MemMgrCtrlOp4(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint max_long_term_frame_idx_plus1)
+{
+ int ii;
+
+ video->MaxLongTermFrameIdx = max_long_term_frame_idx_plus1 - 1;
+
+ /* then mark long term frame with exceeding LongTermFrameIdx to unused for reference. */
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsLongTerm && dpb->fs[ii] != video->currFS)
+ {
+ if (dpb->fs[ii]->LongTermFrameIdx > video->MaxLongTermFrameIdx)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.5.4.5 mark all reference picture as "unused for reference" and setting
+MaxLongTermFrameIdx to "no long-term frame indices" */
+void MemMgrCtrlOp5(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb)
+{
+ int ii;
+
+ video->MaxLongTermFrameIdx = -1;
+ for (ii = 0; ii < dpb->num_fs; ii++) /* including the current frame ??????*/
+ {
+ if (dpb->fs[ii] != video->currFS) // MC_FIX
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+
+ video->mem_mgr_ctrl_eq_5 = TRUE;
+}
+
+/* see subclause 8.2.5.4.6 assing long-term frame index to the current picture */
+void MemMgrCtrlOp6(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_idx)
+{
+
+ unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx);
+ video->currFS->IsLongTerm = 3;
+ video->currFS->IsReference = 3;
+
+ video->currPic->isLongTerm = TRUE;
+ video->currPic->isReference = TRUE;
+ video->currFS->LongTermFrameIdx = long_term_frame_idx;
+}
+
+
+void unmark_for_reference(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint idx)
+{
+
+ AVCFrameStore *fs = dpb->fs[idx];
+ fs->frame.isReference = FALSE;
+ fs->frame.isLongTerm = FALSE;
+
+ fs->IsLongTerm = 0;
+ fs->IsReference = 0;
+ fs->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (fs->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, idx);
+ }
+#endif
+ return ;
+}
+
+void unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint long_term_frame_idx)
+{
+ int ii;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+
+ if (dpb->fs[ii]->IsLongTerm && (dpb->fs[ii]->LongTermFrameIdx == (int)long_term_frame_idx))
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/fmo.cpp b/media/libstagefright/codecs/avc/common/src/fmo.cpp
new file mode 100644
index 0000000..d66eba3
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/fmo.cpp
@@ -0,0 +1,249 @@
+/* ------------------------------------------------------------------
+ * 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 "avclib_common.h"
+
+/* see subclause 8.2.2 Decoding process for macroblock to slice group map */
+OSCL_EXPORT_REF AVCStatus FMOInit(AVCCommonObj *video)
+{
+ AVCPicParamSet *currPPS = video->currPicParams;
+ int *MbToSliceGroupMap = video->MbToSliceGroupMap;
+ int PicSizeInMapUnits = video->PicSizeInMapUnits;
+ int PicWidthInMbs = video->PicWidthInMbs;
+
+ if (currPPS->num_slice_groups_minus1 == 0)
+ {
+ memset(video->MbToSliceGroupMap, 0, video->PicSizeInMapUnits*sizeof(uint));
+ }
+ else
+ {
+ switch (currPPS->slice_group_map_type)
+ {
+ case 0:
+ FmoGenerateType0MapUnitMap(MbToSliceGroupMap, currPPS->run_length_minus1, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 1:
+ FmoGenerateType1MapUnitMap(MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 2:
+ FmoGenerateType2MapUnitMap(currPPS, MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 3:
+ FmoGenerateType3MapUnitMap(video, currPPS, MbToSliceGroupMap, PicWidthInMbs);
+ break;
+ case 4:
+ FmoGenerateType4MapUnitMap(MbToSliceGroupMap, video->MapUnitsInSliceGroup0, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
+ break;
+ case 5:
+ FmoGenerateType5MapUnitMap(MbToSliceGroupMap, video, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
+ break;
+ case 6:
+ FmoGenerateType6MapUnitMap(MbToSliceGroupMap, (int*)currPPS->slice_group_id, PicSizeInMapUnits);
+ break;
+ default:
+ return AVC_FAIL; /* out of range, shouldn't come this far */
+ }
+ }
+
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.2.1 interleaved slice group map type*/
+void FmoGenerateType0MapUnitMap(int *mapUnitToSliceGroupMap, uint *run_length_minus1, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ uint iGroup, j;
+ uint i = 0;
+ do
+ {
+ for (iGroup = 0;
+ (iGroup <= num_slice_groups_minus1) && (i < PicSizeInMapUnits);
+ i += run_length_minus1[iGroup++] + 1)
+ {
+ for (j = 0; j <= run_length_minus1[ iGroup ] && i + j < PicSizeInMapUnits; j++)
+ mapUnitToSliceGroupMap[i+j] = iGroup;
+ }
+ }
+ while (i < PicSizeInMapUnits);
+}
+
+/* see subclause 8.2.2.2 dispersed slice group map type*/
+void FmoGenerateType1MapUnitMap(int *mapUnitToSliceGroupMap, int PicWidthInMbs, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ uint i;
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[i] = ((i % PicWidthInMbs) + (((i / PicWidthInMbs) * (num_slice_groups_minus1 + 1)) / 2))
+ % (num_slice_groups_minus1 + 1);
+ }
+}
+
+/* see subclause 8.2.2.3 foreground with left-over slice group map type */
+void FmoGenerateType2MapUnitMap(AVCPicParamSet *pps, int *mapUnitToSliceGroupMap, int PicWidthInMbs,
+ uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ int iGroup;
+ uint i, x, y;
+ uint yTopLeft, xTopLeft, yBottomRight, xBottomRight;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[ i ] = num_slice_groups_minus1;
+ }
+
+ for (iGroup = num_slice_groups_minus1 - 1 ; iGroup >= 0; iGroup--)
+ {
+ yTopLeft = pps->top_left[ iGroup ] / PicWidthInMbs;
+ xTopLeft = pps->top_left[ iGroup ] % PicWidthInMbs;
+ yBottomRight = pps->bottom_right[ iGroup ] / PicWidthInMbs;
+ xBottomRight = pps->bottom_right[ iGroup ] % PicWidthInMbs;
+ for (y = yTopLeft; y <= yBottomRight; y++)
+ {
+ for (x = xTopLeft; x <= xBottomRight; x++)
+ {
+ mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = iGroup;
+ }
+ }
+ }
+}
+
+
+/* see subclause 8.2.2.4 box-out slice group map type */
+/* follow the text rather than the JM, it's quite different. */
+void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
+ int PicWidthInMbs)
+{
+ uint i, k;
+ int leftBound, topBound, rightBound, bottomBound;
+ int x, y, xDir, yDir;
+ int mapUnitVacant;
+ uint PicSizeInMapUnits = video->PicSizeInMapUnits;
+ uint MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[ i ] = 1;
+ }
+
+ x = (PicWidthInMbs - pps->slice_group_change_direction_flag) / 2;
+ y = (video->PicHeightInMapUnits - pps->slice_group_change_direction_flag) / 2;
+
+ leftBound = x;
+ topBound = y;
+ rightBound = x;
+ bottomBound = y;
+
+ xDir = pps->slice_group_change_direction_flag - 1;
+ yDir = pps->slice_group_change_direction_flag;
+
+ for (k = 0; k < MapUnitsInSliceGroup0; k += mapUnitVacant)
+ {
+ mapUnitVacant = (mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] == 1);
+ if (mapUnitVacant)
+ {
+ mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = 0;
+ }
+
+ if (xDir == -1 && x == leftBound)
+ {
+ leftBound = AVC_MAX(leftBound - 1, 0);
+ x = leftBound;
+ xDir = 0;
+ yDir = 2 * pps->slice_group_change_direction_flag - 1;
+ }
+ else if (xDir == 1 && x == rightBound)
+ {
+ rightBound = AVC_MIN(rightBound + 1, (int)PicWidthInMbs - 1);
+ x = rightBound;
+ xDir = 0;
+ yDir = 1 - 2 * pps->slice_group_change_direction_flag;
+ }
+ else if (yDir == -1 && y == topBound)
+ {
+ topBound = AVC_MAX(topBound - 1, 0);
+ y = topBound;
+ xDir = 1 - 2 * pps->slice_group_change_direction_flag;
+ yDir = 0;
+ }
+ else if (yDir == 1 && y == bottomBound)
+ {
+ bottomBound = AVC_MIN(bottomBound + 1, (int)video->PicHeightInMapUnits - 1);
+ y = bottomBound;
+ xDir = 2 * pps->slice_group_change_direction_flag - 1;
+ yDir = 0;
+ }
+ else
+ {
+ x = x + xDir;
+ y = y + yDir;
+ }
+ }
+}
+
+/* see subclause 8.2.2.5 raster scan slice group map types */
+void FmoGenerateType4MapUnitMap(int *mapUnitToSliceGroupMap, int MapUnitsInSliceGroup0, int slice_group_change_direction_flag, uint PicSizeInMapUnits)
+{
+ uint sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
+
+ uint i;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ if (i < sizeOfUpperLeftGroup)
+ mapUnitToSliceGroupMap[ i ] = 1 - slice_group_change_direction_flag;
+ else
+ mapUnitToSliceGroupMap[ i ] = slice_group_change_direction_flag;
+
+}
+
+/* see subclause 8.2.2.6, wipe slice group map type. */
+void FmoGenerateType5MapUnitMap(int *mapUnitToSliceGroupMap, AVCCommonObj *video,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits)
+{
+ int PicWidthInMbs = video->PicWidthInMbs;
+ int PicHeightInMapUnits = video->PicHeightInMapUnits;
+ int MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
+ int sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
+ int i, j, k = 0;
+
+ for (j = 0; j < PicWidthInMbs; j++)
+ {
+ for (i = 0; i < PicHeightInMapUnits; i++)
+ {
+ if (k++ < sizeOfUpperLeftGroup)
+ {
+ mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = 1 - slice_group_change_direction_flag;
+ }
+ else
+ {
+ mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = slice_group_change_direction_flag;
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.2.7, explicit slice group map */
+void FmoGenerateType6MapUnitMap(int *mapUnitToSliceGroupMap, int *slice_group_id, uint PicSizeInMapUnits)
+{
+ uint i;
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[i] = slice_group_id[i];
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/mb_access.cpp b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
new file mode 100644
index 0000000..414b8f7
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
@@ -0,0 +1,471 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include <string.h>
+
+#include "avclib_common.h"
+
+OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum)
+{
+ int PicWidthInMbs = video->PicWidthInMbs;
+
+ // do frame-only and postpone intraAvail calculattion
+ video->mbAddrA = mbNum - 1;
+ video->mbAddrB = mbNum - PicWidthInMbs;
+ video->mbAddrC = mbNum - PicWidthInMbs + 1;
+ video->mbAddrD = mbNum - PicWidthInMbs - 1;
+
+ video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0;
+ if (video->mb_x)
+ {
+ video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id);
+ if (video->mb_y)
+ {
+ video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id);
+ }
+ }
+
+ if (video->mb_y)
+ {
+ video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id);
+ if (video->mb_x < (PicWidthInMbs - 1))
+ {
+ video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id);
+ }
+ }
+ return ;
+}
+
+bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr)
+{
+ if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs)
+ {
+ return FALSE;
+ }
+
+ if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr; */
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (i)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+3];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[12+i];
+ cnt++;
+ }
+ }
+
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+
+}
+
+
+OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+ if (i&1)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+i+1];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j&1)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[20+i];
+ cnt++;
+ }
+
+ }
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+}
+
+OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag)
+{
+ AVCMacroblock *currMB = video->currMB;
+ AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D;
+ int block_x, block_y, block_x_1, block_y_1, new_block_x;
+ int mbPartIdx, subMbPartIdx, offset_indx;
+ int16 *mv, pmv_x, pmv_y;
+ int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y;
+ int avail_a, avail_b, avail_c;
+ const static uint32 C = 0x5750;
+ int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx;
+ int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0;
+
+ /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to 0 and set ref to -1! */
+ /* we have to populate refIdx as well */
+
+
+ MB_A = &video->mblock[video->mbAddrA];
+ MB_B = &video->mblock[video->mbAddrB];
+
+
+ if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */
+ {
+ currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0;
+ if (video->mbAvailA && video->mbAvailB)
+ {
+ if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
+ (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ }
+ else
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ video->mvd_l0[0][0][0] = 0;
+ video->mvd_l0[0][0][1] = 0;
+ }
+
+ MB_C = &video->mblock[video->mbAddrC];
+ MB_D = &video->mblock[video->mbAddrD];
+
+ offset_MbPart_indx = 0;
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ offset_indx = 0;
+ nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2;
+ nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2;
+ mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1;
+ mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2;
+
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1);
+ block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1);
+
+ block_x_1 = block_x - 1;
+ block_y_1 = block_y - 1;
+ refIdxLXA = refIdxLXB = refIdxLXC = -1;
+ pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0;
+
+ if (block_x)
+ {
+ avail_a = 1;
+ refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ else
+ {
+ avail_a = video->mbAvailA;
+ if (avail_a)
+ {
+ refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ }
+
+ if (block_y)
+ {
+ avail_b = 1;
+ refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+
+ else
+ {
+ avail_b = video->mbAvailB;
+ if (avail_b)
+ {
+ refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+ }
+
+ new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1;
+ avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1;
+
+ if (avail_c)
+ {
+ /* it guaranteed that block_y > 0 && new_block_x<3 ) */
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else
+ {
+ if (block_y == 0 && new_block_x < 3)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_y == 0 && new_block_x == 3)
+ {
+ avail_c = video->mbAvailC;
+ if (avail_c)
+ {
+ refIdxLXC = MB_C->ref_idx_L0[2];
+ mv = (int16*)(MB_C->mvL0 + 12);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+
+ if (avail_c == 0)
+ { /* check D */
+ if (block_x && block_y)
+ {
+ avail_c = 1;
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else if (block_y)
+ {
+ avail_c = video->mbAvailA;
+ if (avail_c)
+ {
+ refIdxLXC = MB_A->ref_idx_L0[(block_y_1 & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_x)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else
+ {
+ avail_c = video->mbAvailD;
+ if (avail_c)
+ {
+ refIdxLXC = MB_D->ref_idx_L0[3];
+ mv = (int16*)(MB_D->mvL0 + 15);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ }
+ }
+
+ offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+
+ curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)];
+
+ if (avail_a && !(avail_b || avail_c))
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1)
+ {
+ if (curr_ref_idx == refIdxLXA)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (curr_ref_idx == refIdxLXB)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ else
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ else
+ {
+ pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x);
+ pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y);
+ }
+
+ /* overwrite if special case */
+ if (currMB->NumMbPart == 2)
+ {
+ if (currMB->MbPartWidth == 16)
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXB == curr_ref_idx)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ }
+ else if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else if (refIdxLXC == curr_ref_idx)
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ }
+
+ mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+
+ if (encFlag) /* calculate residual MV video->mvd_l0 */
+ {
+ video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x;
+ video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y;
+ }
+ else /* calculate original MV currMB->mvL0 */
+ {
+ pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0];
+ pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1];
+
+ for (i = 0; i < nmSubMbHeight; i++)
+ {
+ for (j = 0; j < nmSubMbWidth; j++)
+ {
+ *mv++ = pmv_x;
+ *mv++ = pmv_y;
+ }
+ mv += (8 - (j << 1));
+ }
+ }
+ }
+ offset_MbPart_indx = currMB->MbPartWidth >> 4;
+
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/reflist.cpp b/media/libstagefright/codecs/avc/common/src/reflist.cpp
new file mode 100644
index 0000000..4ddc7dd
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/reflist.cpp
@@ -0,0 +1,596 @@
+/* ------------------------------------------------------------------
+ * 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"
+
+/** see subclause 8.2.4 Decoding process for reference picture lists construction. */
+OSCL_EXPORT_REF void RefListInit(AVCCommonObj *video)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int slice_type = video->slice_type;
+ int i, list0idx;
+
+ AVCPictureData *tmp_s;
+
+ list0idx = 0;
+
+ if (slice_type == AVC_I_SLICE)
+ {
+ video->refList0Size = 0;
+ video->refList1Size = 0;
+
+ /* we still have to calculate FrameNumWrap to make sure that all I-slice clip
+ can perform sliding_window_operation properly. */
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
+ }
+ else
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
+ }
+ dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
+ }
+ }
+
+
+ return ;
+ }
+ if (slice_type == AVC_P_SLICE)
+ {
+ /* Calculate FrameNumWrap and PicNum */
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
+ }
+ else
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
+ }
+ dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
+ video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
+ }
+ }
+
+ if (list0idx == 0)
+ {
+ dpb->fs[0]->IsReference = 3;
+ video->RefPicList0[0] = &(dpb->fs[0]->frame);
+ list0idx = 1;
+ }
+ /* order list 0 by PicNum from max to min, see subclause 8.2.4.2.1 */
+ SortPicByPicNum(video->RefPicList0, list0idx);
+ video->refList0Size = list0idx;
+
+ /* long term handling */
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i]->IsLongTerm == 3)
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ dpb->fs[i]->frame.LongTermPicNum = dpb->fs[i]->LongTermFrameIdx;
+ video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
+ }
+ }
+
+ /* order PicNum from min to max, see subclause 8.2.4.2.1 */
+ SortPicByPicNumLongTerm(&(video->RefPicList0[video->refList0Size]), list0idx - video->refList0Size);
+ video->refList0Size = list0idx;
+
+
+ video->refList1Size = 0;
+ }
+
+
+ if ((video->refList0Size == video->refList1Size) && (video->refList0Size > 1))
+ {
+ /* check if lists are identical, if yes swap first two elements of listX[1] */
+ /* last paragraph of subclause 8.2.4.2.4 */
+
+ for (i = 0; i < video->refList0Size; i++)
+ {
+ if (video->RefPicList0[i] != video->RefPicList1[i])
+ {
+ break;
+ }
+ }
+ if (i == video->refList0Size)
+ {
+ tmp_s = video->RefPicList1[0];
+ video->RefPicList1[0] = video->RefPicList1[1];
+ video->RefPicList1[1] = tmp_s;
+ }
+ }
+
+ /* set max size */
+ video->refList0Size = AVC_MIN(video->refList0Size, (int)video->sliceHdr->num_ref_idx_l0_active_minus1 + 1);
+ video->refList1Size = AVC_MIN(video->refList1Size, (int)video->sliceHdr->num_ref_idx_l1_active_minus1 + 1);
+
+ return ;
+}
+/* see subclause 8.2.4.3 */
+OSCL_EXPORT_REF AVCStatus ReOrderList(AVCCommonObj *video)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCStatus status = AVC_SUCCESS;
+ int slice_type = video->slice_type;
+
+ if (slice_type != AVC_I_SLICE)
+ {
+ if (sliceHdr->ref_pic_list_reordering_flag_l0)
+ {
+ status = ReorderRefPicList(video, 0);
+ if (status != AVC_SUCCESS)
+ return status;
+ }
+ if (video->refList0Size == 0)
+ {
+ return AVC_FAIL;
+ }
+ }
+ return status;
+}
+
+AVCStatus ReorderRefPicList(AVCCommonObj *video, int isL1)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCStatus status;
+
+ int *list_size;
+ int num_ref_idx_lX_active_minus1;
+ uint *remapping_of_pic_nums_idc;
+ int *abs_diff_pic_num_minus1;
+ int *long_term_pic_idx;
+ int i;
+ int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
+ int refIdxLX = 0;
+ void* tmp;
+
+ if (!isL1) /* list 0 */
+ {
+ list_size = &(video->refList0Size);
+ num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l0_active_minus1;
+ remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l0;
+ tmp = (void*)sliceHdr->abs_diff_pic_num_minus1_l0;
+ abs_diff_pic_num_minus1 = (int*) tmp;
+ tmp = (void*)sliceHdr->long_term_pic_num_l0;
+ long_term_pic_idx = (int*) tmp;
+ }
+ else
+ {
+ list_size = &(video->refList1Size);
+ num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l1_active_minus1;
+ remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l1;
+ tmp = (void*) sliceHdr->abs_diff_pic_num_minus1_l1;
+ abs_diff_pic_num_minus1 = (int*) tmp;
+ tmp = (void*) sliceHdr->long_term_pic_num_l1;
+ long_term_pic_idx = (int*)tmp;
+ }
+
+ maxPicNum = video->MaxPicNum;
+ currPicNum = video->CurrPicNum;
+
+ picNumLXPred = currPicNum; /* initial value */
+
+ for (i = 0; remapping_of_pic_nums_idc[i] != 3; i++)
+ {
+ if ((remapping_of_pic_nums_idc[i] > 3) || (i >= MAX_REF_PIC_LIST_REORDERING))
+ {
+ return AVC_FAIL; /* out of range */
+ }
+ /* see subclause 8.2.4.3.1 */
+ if (remapping_of_pic_nums_idc[i] < 2)
+ {
+ if (remapping_of_pic_nums_idc[i] == 0)
+ {
+ if (picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) < 0)
+ picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) + maxPicNum;
+ else
+ picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1);
+ }
+ else /* (remapping_of_pic_nums_idc[i] == 1) */
+ {
+ if (picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) >= maxPicNum)
+ picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) - maxPicNum;
+ else
+ picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1);
+ }
+ picNumLXPred = picNumLXNoWrap; /* prediction for the next one */
+
+ if (picNumLXNoWrap > currPicNum)
+ picNumLX = picNumLXNoWrap - maxPicNum;
+ else
+ picNumLX = picNumLXNoWrap;
+
+ status = ReorderShortTerm(video, picNumLX, &refIdxLX, isL1);
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ else /* (remapping_of_pic_nums_idc[i] == 2), subclause 8.2.4.3.2 */
+ {
+ status = ReorderLongTerm(video, long_term_pic_idx[i], &refIdxLX, isL1);
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ /* that's a definition */
+ *list_size = num_ref_idx_lX_active_minus1 + 1;
+
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.4.3.1 */
+AVCStatus ReorderShortTerm(AVCCommonObj *video, int picNumLX, int *refIdxLX, int isL1)
+{
+ int cIdx, nIdx;
+ int num_ref_idx_lX_active_minus1;
+ AVCPictureData *picLX, **RefPicListX;
+
+ if (!isL1) /* list 0 */
+ {
+ RefPicListX = video->RefPicList0;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
+ }
+ else
+ {
+ RefPicListX = video->RefPicList1;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
+ }
+
+ picLX = GetShortTermPic(video, picNumLX);
+
+ if (picLX == NULL)
+ {
+ return AVC_FAIL;
+ }
+ /* Note RefPicListX has to access element number num_ref_idx_lX_active */
+ /* There could be access violation here. */
+ if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
+ {
+ return AVC_FAIL;
+ }
+
+ for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
+ {
+ RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
+ }
+
+ RefPicListX[(*refIdxLX)++ ] = picLX;
+
+ nIdx = *refIdxLX;
+
+ for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
+ {
+ if (RefPicListX[ cIdx ])
+ {
+ if ((RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->PicNum != picNumLX))
+ {
+ RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
+ }
+ }
+ }
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.4.3.2 */
+AVCStatus ReorderLongTerm(AVCCommonObj *video, int LongTermPicNum, int *refIdxLX, int isL1)
+{
+ AVCPictureData **RefPicListX;
+ int num_ref_idx_lX_active_minus1;
+ int cIdx, nIdx;
+ AVCPictureData *picLX;
+
+ if (!isL1) /* list 0 */
+ {
+ RefPicListX = video->RefPicList0;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
+ }
+ else
+ {
+ RefPicListX = video->RefPicList1;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
+ }
+
+ picLX = GetLongTermPic(video, LongTermPicNum);
+ if (picLX == NULL)
+ {
+ return AVC_FAIL;
+ }
+ /* Note RefPicListX has to access element number num_ref_idx_lX_active */
+ /* There could be access violation here. */
+ if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
+ {
+ return AVC_FAIL;
+ }
+ for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
+ RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
+
+ RefPicListX[(*refIdxLX)++ ] = picLX;
+
+ nIdx = *refIdxLX;
+
+ for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
+ {
+ if ((!RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->LongTermPicNum != LongTermPicNum))
+ {
+ RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
+ }
+ }
+ return AVC_SUCCESS;
+}
+
+
+AVCPictureData* GetShortTermPic(AVCCommonObj *video, int picNum)
+{
+ int i;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+
+ if (dpb->fs[i]->IsReference == 3)
+ {
+ if ((dpb->fs[i]->frame.isLongTerm == FALSE) && (dpb->fs[i]->frame.PicNum == picNum))
+ {
+ return &(dpb->fs[i]->frame);
+ }
+ }
+
+ }
+
+ return NULL;
+}
+
+AVCPictureData* GetLongTermPic(AVCCommonObj *video, int LongtermPicNum)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int i;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+
+ if (dpb->fs[i]->IsReference == 3)
+ {
+ if ((dpb->fs[i]->frame.isLongTerm == TRUE) && (dpb->fs[i]->frame.LongTermPicNum == LongtermPicNum))
+ {
+ return &(dpb->fs[i]->frame);
+ }
+ }
+
+ }
+ return NULL;
+}
+
+int is_short_ref(AVCPictureData *s)
+{
+ return ((s->isReference) && !(s->isLongTerm));
+}
+
+int is_long_ref(AVCPictureData *s)
+{
+ return ((s->isReference) && (s->isLongTerm));
+}
+
+
+/* sort by PicNum, descending order */
+void SortPicByPicNum(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicNum > data[i]->PicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort by PicNum, ascending order */
+void SortPicByPicNumLongTerm(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+
+/* sort by FrameNumWrap, descending order */
+void SortFrameByFrameNumWrap(AVCFrameStore *data[], int num)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->FrameNumWrap > data[i]->FrameNumWrap)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort frames by LongTermFrameIdx, ascending order */
+void SortFrameByLTFrameIdx(AVCFrameStore *data[], int num)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermFrameIdx < data[i]->LongTermFrameIdx)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort PictureData by POC in descending order */
+void SortPicByPOC(AVCPictureData *data[], int num, int descending)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ if (descending)
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ return ;
+}
+
+/* sort PictureData by LongTermPicNum in ascending order */
+void SortPicByLTPicNum(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort by PicOrderCnt, descending order */
+void SortFrameByPOC(AVCFrameStore *data[], int num, int descending)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ if (descending)
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+
+ return ;
+}
+
+
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;
+}
diff --git a/media/libstagefright/codecs/avc/patent_disclaimer.txt b/media/libstagefright/codecs/avc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/patent_disclaimer.txt
@@ -0,0 +1,9 @@
+
+THIS IS NOT A GRANT OF PATENT RIGHTS.
+
+Google makes no representation or warranty that the codecs for which
+source code is made available hereunder are unencumbered by
+third-party patents. Those intending to use this source code in
+hardware or software products are advised that implementations of
+these codecs, including in open source software or shareware, may
+require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index cb2788c..fb56a93 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -51,10 +51,6 @@ LOCAL_C_INCLUDES := \
LOCAL_CFLAGS := \
-DOSCL_UNUSED_ARG=
-LOCAL_SHARED_LIBRARIES := \
- libstagefright \
- libutils
-
LOCAL_MODULE := libstagefright_mp3dec
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
new file mode 100644
index 0000000..0146f77
--- /dev/null
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AVC_DECODER_H_
+
+#define AVC_DECODER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+struct tagAVCHandle;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct AVCDecoder : public MediaSource,
+ public MediaBufferObserver {
+ AVCDecoder(const sp<MediaSource> &source);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+protected:
+ virtual ~AVCDecoder();
+
+private:
+ sp<MediaSource> mSource;
+ bool mStarted;
+
+ sp<MetaData> mFormat;
+
+ Vector<MediaBuffer *> mCodecSpecificData;
+
+ tagAVCHandle *mHandle;
+ Vector<MediaBuffer *> mFrames;
+ MediaBuffer *mInputBuffer;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumSamplesOutput;
+
+ void addCodecSpecificData(const uint8_t *data, size_t size);
+
+ static int32_t ActivateSPSWrapper(
+ void *userData, unsigned int sizeInMbs, unsigned int numBuffers);
+
+ static int32_t BindFrameWrapper(
+ void *userData, int32_t index, uint8_t **yuv);
+
+ static void UnbindFrame(void *userData, int32_t index);
+
+ int32_t activateSPS(
+ unsigned int sizeInMbs, unsigned int numBuffers);
+
+ int32_t bindFrame(int32_t index, uint8_t **yuv);
+
+ void releaseFrames();
+
+ AVCDecoder(const AVCDecoder &);
+ AVCDecoder &operator=(const AVCDecoder &);
+};
+
+} // namespace android
+
+#endif // AVC_DECODER_H_