summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/avc/common
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-12-10 09:44:29 -0800
committerAndreas Huber <andih@google.com>2009-12-10 14:43:44 -0800
commit609f1a00c96cf5605f4614e7bb6d0487c98969c5 (patch)
tree31aa2b3d1787a2f236b733ab27dff8aff04b3197 /media/libstagefright/codecs/avc/common
parentdf08a8102aa0721afec6df5db8f5742f5542473c (diff)
downloadframeworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.zip
frameworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.tar.gz
frameworks_av-609f1a00c96cf5605f4614e7bb6d0487c98969c5.tar.bz2
Initial checkin of software AVC video decoder based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/avc/common')
-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
10 files changed, 5452 insertions, 0 deletions
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 ;
+}
+
+