From ab74f5c79e6b22c12173b63f7a127b4dc8f4882e Mon Sep 17 00:00:00 2001
From: Karsten Suehring <karsten.suehring@hhi.fraunhofer.de>
Date: Mon, 25 Mar 2019 19:10:50 +0100
Subject: [PATCH] import JM 14.1

---
 CHANGES.TXT                      |   34 +-
 bin/encoder.cfg                  |   75 +-
 bin/encoder_yuv422.cfg           |  112 +-
 doc/ldecod.dox                   |    2 +-
 doc/lencod.dox                   |    2 +-
 ldecod/inc/annexb.h              |    2 +-
 ldecod/inc/block.h               |   31 +-
 ldecod/inc/global.h              |  115 +-
 ldecod/inc/ifunctions.h          |   19 +
 ldecod/inc/macroblock.h          |  303 +----
 ldecod/inc/mbuffer.h             |   69 +-
 ldecod/inc/memalloc.h            |   44 +-
 ldecod/inc/nalu.h                |    3 +-
 ldecod/inc/quant.h               |   50 +
 ldecod/inc/rtp.h                 |    2 +-
 ldecod/inc/transform8x8.h        |    3 +-
 ldecod/src/annexb.c              |   12 +-
 ldecod/src/block.c               |  956 ++++---------
 ldecod/src/cabac.c               |  390 ++----
 ldecod/src/erc_do_p.c            |   37 +-
 ldecod/src/filehandle.c          |   11 +
 ldecod/src/header.c              |   10 +-
 ldecod/src/image.c               |  160 +--
 ldecod/src/ldecod.c              |   30 +-
 ldecod/src/loopFilter.c          |   35 +-
 ldecod/src/macroblock.c          | 2170 ++++++++++++++++--------------
 ldecod/src/mb_access.c           |    8 +-
 ldecod/src/mbuffer.c             | 1056 +++++++--------
 ldecod/src/mc_prediction.c       |  259 ++--
 ldecod/src/memalloc.c            |   52 +-
 ldecod/src/nalu.c                |   47 +-
 ldecod/src/output.c              |   20 +-
 ldecod/src/parset.c              |   22 +-
 ldecod/src/quant.c               |  459 +++++++
 ldecod/src/rtp.c                 |   18 +-
 ldecod/src/sei.c                 |    2 +-
 ldecod/src/transform8x8.c        |  160 +--
 ldecod/src/vlc.c                 |   28 +-
 ldecod_vc7.vcproj                |    9 +
 ldecod_vc8.vcproj                |    9 +
 lencod/inc/block.h               |  134 +-
 lencod/inc/cconv_yuv2rgb.h       |   26 +
 lencod/inc/configfile.h          |   30 +-
 lencod/inc/conformance.h         |    2 +-
 lencod/inc/defines.h             |   14 +-
 lencod/inc/enc_statistics.h      |   64 +
 lencod/inc/errdo.h               |   34 +
 lencod/inc/errdo_mc_prediction.h |   35 +
 lencod/inc/filehandle.h          |   25 +
 lencod/inc/frame.h               |    4 +
 lencod/inc/global.h              |  375 ++----
 lencod/inc/ifunctions.h          |   19 +
 lencod/inc/image.h               |   11 +-
 lencod/inc/img_dist_ms_ssim.h    |   25 +
 lencod/inc/img_dist_snr.h        |   24 +
 lencod/inc/img_dist_ssim.h       |   26 +
 lencod/inc/img_distortion.h      |   33 +
 lencod/inc/macroblock.h          |    7 +-
 lencod/inc/mb_access.h           |    3 +-
 lencod/inc/mbuffer.h             |   78 +-
 lencod/inc/mc_prediction.h       |   10 +-
 lencod/inc/me_epzs.h             |   21 +-
 lencod/inc/me_fullfast.h         |    6 +-
 lencod/inc/me_fullsearch.h       |    2 +-
 lencod/inc/me_umhex.h            |    1 +
 lencod/inc/me_umhexsmp.h         |    1 +
 lencod/inc/memalloc.h            |   55 +-
 lencod/inc/mode_decision.h       |   28 +-
 lencod/inc/mv-search.h           |    5 +-
 lencod/inc/q_around.h            |   44 +
 lencod/inc/quant4x4.h            |   79 +-
 lencod/inc/quant8x8.h            |    2 +-
 lencod/inc/quantChroma.h         |   59 +
 lencod/inc/ratectl.h             |    2 -
 lencod/inc/rc_quadratic.h        |    2 +-
 lencod/inc/rdo_quant.h           |   10 +-
 lencod/inc/rdopt.h               |   25 +-
 lencod/inc/report.h              |   25 +
 lencod/inc/slice.h               |   37 +
 lencod/inc/vlc.h                 |   30 +-
 lencod/inc/wp.h                  |   24 +-
 lencod/inc/wp_lms.h              |   26 +
 lencod/inc/wp_mcprec.h           |   64 +
 lencod/src/block.c               | 1198 +++++++++--------
 lencod/src/cabac.c               |  299 ++--
 lencod/src/cconv_yuv2rgb.c       |  122 ++
 lencod/src/configfile.c          |  112 +-
 lencod/src/conformance.c         |    5 -
 lencod/src/context_ini.c         |    2 +-
 lencod/src/decoder.c             |  669 ---------
 lencod/src/errdo.c               |  580 ++++++++
 lencod/src/errdo_mc_prediction.c | 1295 ++++++++++++++++++
 lencod/src/explicit_gop.c        |   74 +-
 lencod/src/filehandle.c          |    1 +
 lencod/src/header.c              |   13 +-
 lencod/src/image.c               | 1013 ++++++--------
 lencod/src/img_dist_ms_ssim.c    |  353 +++++
 lencod/src/img_dist_snr.c        |   52 +
 lencod/src/img_dist_ssim.c       |  113 ++
 lencod/src/img_distortion.c      |  210 +++
 lencod/src/input.c               |    3 +-
 lencod/src/lencod.c              | 1471 ++++----------------
 lencod/src/loopFilter.c          |   24 +-
 lencod/src/macroblock.c          |  358 +++--
 lencod/src/mb_access.c           |   10 +-
 lencod/src/mbuffer.c             | 1145 ++++++++--------
 lencod/src/mc_prediction.c       |   92 +-
 lencod/src/md_high.c             |  120 +-
 lencod/src/md_highfast.c         |  144 +-
 lencod/src/md_highloss.c         |  116 +-
 lencod/src/md_low.c              |  164 ++-
 lencod/src/me_epzs.c             |  663 +++++----
 lencod/src/me_fullfast.c         |   18 +-
 lencod/src/me_fullsearch.c       |    1 +
 lencod/src/me_umhex.c            |   22 +-
 lencod/src/me_umhexsmp.c         |    1 +
 lencod/src/memalloc.c            |  430 +++++-
 lencod/src/mode_decision.c       |  406 +++---
 lencod/src/mv-search.c           |  314 ++---
 lencod/src/nal.c                 |    1 +
 lencod/src/parset.c              |    3 +-
 lencod/src/q_around.c            |  369 +++++
 lencod/src/q_matrix.c            |  150 ++-
 lencod/src/q_offsets.c           |   10 +-
 lencod/src/quant4x4.c            |   15 +-
 lencod/src/quant4x4_around.c     |  176 ++-
 lencod/src/quant4x4_normal.c     |  174 ++-
 lencod/src/quant4x4_trellis.c    |  270 ++--
 lencod/src/quant8x8.c            |    2 +-
 lencod/src/quant8x8_around.c     |   91 +-
 lencod/src/quant8x8_normal.c     |   48 +-
 lencod/src/quant8x8_trellis.c    |  166 +--
 lencod/src/quantChroma.c         |   57 +
 lencod/src/quantChroma_around.c  |  171 +++
 lencod/src/quantChroma_normal.c  |  171 +++
 lencod/src/quantChroma_trellis.c |  173 +++
 lencod/src/ratectl.c             |    7 +-
 lencod/src/rc_quadratic.c        |  144 +-
 lencod/src/rd_intra_jm.c         |   65 +-
 lencod/src/rdo_quant.c           |  433 ++++--
 lencod/src/rdopt.c               | 1291 +++++++-----------
 lencod/src/rdpicdecision.c       |   13 +-
 lencod/src/refbuf.c              |    2 +-
 lencod/src/report.c              | 1181 ++++++++++++++++
 lencod/src/slice.c               |  627 ++++++---
 lencod/src/transform8x8.c        |  264 ++--
 lencod/src/vlc.c                 |   14 +-
 lencod/src/weighted_prediction.c |  535 +++++---
 lencod/src/wp_lms.c              |  877 ++++++++++++
 lencod/src/wp_mcprec.c           |  430 ++++++
 lencod_vc7.vcproj                |   99 +-
 lencod_vc8.vcproj                |  129 +-
 152 files changed, 16933 insertions(+), 11191 deletions(-)
 create mode 100644 ldecod/inc/quant.h
 create mode 100644 ldecod/src/quant.c
 create mode 100644 lencod/inc/cconv_yuv2rgb.h
 create mode 100644 lencod/inc/enc_statistics.h
 create mode 100644 lencod/inc/errdo.h
 create mode 100644 lencod/inc/errdo_mc_prediction.h
 create mode 100644 lencod/inc/filehandle.h
 create mode 100644 lencod/inc/img_dist_ms_ssim.h
 create mode 100644 lencod/inc/img_dist_snr.h
 create mode 100644 lencod/inc/img_dist_ssim.h
 create mode 100644 lencod/inc/img_distortion.h
 create mode 100644 lencod/inc/q_around.h
 create mode 100644 lencod/inc/quantChroma.h
 create mode 100644 lencod/inc/report.h
 create mode 100644 lencod/inc/slice.h
 create mode 100644 lencod/inc/wp_lms.h
 create mode 100644 lencod/inc/wp_mcprec.h
 create mode 100644 lencod/src/cconv_yuv2rgb.c
 delete mode 100644 lencod/src/decoder.c
 create mode 100644 lencod/src/errdo.c
 create mode 100644 lencod/src/errdo_mc_prediction.c
 create mode 100644 lencod/src/img_dist_ms_ssim.c
 create mode 100644 lencod/src/img_dist_snr.c
 create mode 100644 lencod/src/img_dist_ssim.c
 create mode 100644 lencod/src/img_distortion.c
 create mode 100644 lencod/src/q_around.c
 create mode 100644 lencod/src/quantChroma.c
 create mode 100644 lencod/src/quantChroma_around.c
 create mode 100644 lencod/src/quantChroma_normal.c
 create mode 100644 lencod/src/quantChroma_trellis.c
 create mode 100644 lencod/src/report.c
 create mode 100644 lencod/src/wp_lms.c
 create mode 100644 lencod/src/wp_mcprec.c

diff --git a/CHANGES.TXT b/CHANGES.TXT
index 5b96fe3..9c61c94 100644
--- a/CHANGES.TXT
+++ b/CHANGES.TXT
@@ -1,3 +1,26 @@
+Changes in Version JM 14.1 (since JM 14.0)
+------------------------------------------
+- encoder: fixes in lossless coding (KHH)
+- encoder: Improved MC precision using Reordering & Weighed Prediction (AL, AT)
+- encoder: Weighted Prediction Extensions (AT, AL)
+- encoder: MS-SSIM distortion computation (PeP)
+- encoder: Rewrite of Error Resilient RDO (PeP, AT)
+- encoder: SSIM distortion computation (ZHL, WK, AT)
+- encoder: RGB color space distortion computation (WK, AT)
+- encoder: Distortion/Statistics functionality cleanups (AT, WK)
+- encoder: RDOQ and Quantization cleanups (LL, AT)
+- encoder: RC cleanups (AT)
+- encoder: Adaptive Rounding Support for Low Complexity RDO (EM)
+- encoder: Multipass RD coding bug fix for PicAFF (AL)
+- decoder: Motion vector limit checking (LlL)
+- encoder/decoder: Various code optimizations (AT)
+- encoder/decoder: Various cleanups /reorganizations (AT)
+- decoder: SP/SI slice decoder fixes (AT)
+- encoder: fix 4:0:0 encoder bit depth initialization (KS)
+- encoder: use SPS id parameter in GenerateSequenceParameterSet (KS)
+- encoder: fix number of bits calculation for pic aff with slices/DP (CS)
+
+
 Changes in Version JM 14.0 (since JM 13.2)
 ------------------------------------------
 - encoder: Bipredictive ME bug fixes (AT)
@@ -958,7 +981,7 @@ Changes for Version JM 4.0c to JM 4.0b
 New features
 * New Macroblock modes for SP-frames [JVT-B055] (RK)
   Note: some problems related to decoding of SI-frames
-  are reported and have to be fixed
+	are reported and have to be fixed
  
 
 
@@ -1262,6 +1285,7 @@ DK      Dimitris Kontopodis     dkonto@eikon.tum.de
 DM      Detlev Marpe            marpe@hhi.de
 DT      Dong Tian               tian@cs.tut.fi
 DW      Dong Wang               Dong.Wang@bristol.ac.uk
+EM      Ehsan Maani             emaan@dolby.com
 ES      Eric Setton             esetton@stanford.edu
 FB      Frank Bossen            bossen@docomolabs-usa.com
 GB      Gabi Blaetterman        blaetter@hhi.de
@@ -1287,10 +1311,12 @@ JX      Jian Feng Xu            fenax@video.mdc.tsinghua.edu.cn
 JXi     Jun Xin                 jxin@merl.com
 JZ      Jun Zhang               j_zhang1999@yahoo.com
 KL      Karl Lillevold          Karll@real.com
+KHH     Ki-Hun Han              khhan@dms.sejong.ac.kr
 KP      Krit Panusopone         KPanusopone@gi.com
 KSa     Kazushi Sato            kazushi@av.crl.sony.co.jp
 LK      Louis Kerofsky          lkerofsky@sharplabs.com
 LL      Limin Liu               lliu@dolby.com
+LlL     Loïc Le Loarer          loic_leloarer@sdesigns.eu
 LW      Limin Wang              liwang@gi.com
 LWi     Lowell Winger           lwinger@videolocus.com
 LP      Luca Pezzoni            luca.pezzoni@st.com
@@ -1303,6 +1329,7 @@ MT      Mario Trentini          mario_trentini@realmagic.fr
 MW      Mathias Wien            wien@ient.rwth-aachen.de
 MWa     Michael Walter          eiMichaelWalter@web.de
 OD      Olivier Deygas          olivier.deygas@st.com
+PeP     Peshala Pahalawatta     Peshala.Pahalawatta@dolby.com
 PK      Petr Kadlec             Kadlec@FTW.at
 PL      Peter List              Peter.List@t-systems.de
 PN      Pavel Novotny           pnovotny@lsil.com
@@ -1348,7 +1375,7 @@ VG      Valeri George           valeri.george@hhi.fraunhofer.de
 VV      Viktor Varsa            viktor.varsa@nokia.com
 WC      Woong Il Choi           creata@ece.skku.ac.kr
 WF      Wenfang Fu              fwf@video.mdc.tsinghua.edu.cn
-WK      Woo-Shik Kim            wskim@sait.samsung.co.kr
+WK      Woo-Shik Kim            wooshik.kim@usc.edu
 WZ      Weimin Zeng             wzeng@wischip.com
 XI      Xin                     xin@apple.com
 XS      Xiaoyan Sun             sunxiaoyan@msrchina.research.microsoft.com   
@@ -1356,13 +1383,14 @@ XX      Xiaozhong Xu            xxz@video.mdc.tsinghua.edu.cn
 XY      Xiaoquan Yi             xyi@scu.edu
 YC      Yi-Jen Chiu             yi-jen.chiu@intel.com
 YD      Yunyang Dai             ydai@dolby.com
-YDh     Yves Dhondt              yves.dhondt@ugent.be
+YDh     Yves Dhondt             yves.dhondt@ugent.be
 YH      Yu-Wen Huang            YW_Huang@mtk.com.tw
 YK      Yoshihiro Kikuchi       yoshihiro.kikuchi@toshiba.co.jp
 YL      Yann Lemaguet           yann.lemaguet@philips.com
 YW      Ye-Kui Wang             ye-kui.wang@nokia.com
 YX      Yanjun Xu               yxu@sarnoff.com
 ZH      Zhou Heng               zhou_heng@yahoo.com
+ZHL     Zhen Li                 zhen.li@dolby.com
 ZL      Li Zhang                zhangli@jdl.ac.cn
 ZX      Z. Xue                  jon_xz@yahoo.com
 ZY      Zheng Yanzhao           yzzheng@singnet.com
diff --git a/bin/encoder.cfg b/bin/encoder.cfg
index e66baaa..64d0a47 100644
--- a/bin/encoder.cfg
+++ b/bin/encoder.cfg
@@ -53,6 +53,7 @@ MEDistortionFPel      = 0   # Select error metric for Full-Pel ME    (0: SAD, 1:
 MEDistortionHPel      = 2   # Select error metric for Half-Pel ME    (0: SAD, 1: SSE, 2: Hadamard SAD)
 MEDistortionQPel      = 2   # Select error metric for Quarter-Pel ME (0: SAD, 1: SSE, 2: Hadamard SAD)
 MDDistortion          = 2   # Select error metric for Mode Decision  (0: SAD, 1: SSE, 2: Hadamard SAD)
+SkipDeBlockNonRef     = 0   # Skip Deblocking (regardless of DFParametersFlag) for non-reference frames (0: off, 1: on)
 ChromaMCBuffer        = 1   # Calculate Color component interpolated values in advance and store them.
                             # Provides a trade-off between memory and computational complexity
                             # (0: disabled/default, 1: enabled)
@@ -90,8 +91,13 @@ BSliceSearch8x4       = 1   # B-Slice Inter block search  8x4  (0=disable, 1=ena
 BSliceSearch4x8       = 1   # B-Slice Inter block search  4x8  (0=disable, 1=enable)
 BSliceSearch4x4       = 1   # B-Slice Inter block search  4x4  (0=disable, 1=enable)
 
-DisableIntra4x4        = 0  # Disable Intra 4x4 mode
-DisableIntra16x16      = 0  # Disable Intra 16x16 mode
+BiPredSearch16x16     = 1   # B-Slice Bi-prediction block search 16x16 (0=disable, 1=enable)
+BiPredSearch16x8      = 1   # B-Slice Bi-prediction block search 16x8  (0=disable, 1=enable)
+BiPredSearch8x16      = 1   # B-Slice Bi-prediction block search 8x16  (0=disable, 1=enable)
+BiPredSearch8x8       = 1   # B-Slice Bi-prediction block search 8x8   (0=disable, 1=enable)
+
+DisableIntra4x4        = 0  # Disable Intra 4x4 modes
+DisableIntra16x16      = 0  # Disable Intra 16x16 modes
 DisableIntraInInter    = 0  # Disable Intra modes for inter slices
 IntraDisableInterOnly  = 0  # Apply Disabling Intra conditions only to Inter Slices (0:disable/default,1: enable)
 Intra4x4ParDisable     = 0  # Disable Vertical & Horizontal 4x4
@@ -178,7 +184,21 @@ IntraBottom              =  0     # Force Intra Bottom at GOP Period
 
 WeightedPrediction       =  0     # P picture Weighted Prediction (0=off, 1=explicit mode)
 WeightedBiprediction     =  0     # B picture Weighted Prediciton (0=off, 1=explicit mode,  2=implicit mode)
+ChromaWeightSupport      =  1     # Enable consideration of weights for Chroma components
 UseWeightedReferenceME   =  1     # Use weighted reference for ME (0=off, 1=on)
+WPMethod                 =  1     # WP method (0: DC based, 1: LMS based)
+EnhancedBWeightSupport   =  0     # Enhanced B Weight support (needs revisit if we wish to merge with WPMethod)
+WPMCPrecision            =  0     # Improved Motion Compensation Precision using WP based methods.
+                                  # Clones WP references with slightly modified rounding offsets (Requires RDPictureDecision and GenerateMultiplePPS) :
+                                  # 0: disabled (default) 
+                                  # 1: Up to one additional coding pass. Ref0 is 0, ref1 is 0 with a -1 offset
+                                  # 2: Up to two additional coding passes. (1) Ref0 is 0, ref1 is 0 with a -1 offset, (1) Ref0 is 0 with a -1 offset, ref1 is 0
+WPMCPrecFullRef          =  0     # Increases the number of references in the reference picture lists to account
+                                  # for the lost reference slot when reordering is used during a coding pass in WPMCPrecision for reference replication.
+                                  # The number of references in non-reordered passes stays unchanged
+WPMCPrecBSlice           =  1     # 2: Apply rounding on every B slice. This efectively disables the evaluation of alternative QPs during RDPictureDecision.
+                                  # 1: Disable rounding for non-reference B slices. Non-reference B slices are evaluated for alternative QPs during RDPictureDecision.
+                                  # 0: Disable rounding for B slices.
 
 ##########################################################################################
 # Picture based Multi-pass encoding
@@ -190,8 +210,8 @@ RDPictureDecision        =  0     # Perform RD optimal decision between differen
 RDPictureIntra           =  0     # Perform RD optimal decision also for intra coded pictures (0: disabled (default), 1: enabled).
 RDPSliceWeightOnly       =  1     # Only consider Weighted Prediction for P slices in Picture RD decision. (0: disabled, 1: enabled (default))
 RDBSliceWeightOnly       =  0     # Only consider Weighted Prediction for B slices in Picture RD decision. (0: disabled (default), 1: enabled )
-RDPSliceBTest            =  1     # Perform Slice level RD decision between P and P slices. 
-                                  # Requires RDPSliceWeightOnly = 0. (0: disabled (default), 1: enabled )
+RDPSliceBTest            =  1     # Perform Slice level RD decision between P and B slices. 
+                                  # Requires GenerateMultiplePPS = 1 and RDPSliceWeightOnly = 0. (0: disabled (default), 1: enabled )
 
 ##########################################################################################
 # Deblocking filter parameters
@@ -251,6 +271,9 @@ RDOptimization         =  1  # rd-optimized mode decision
                              # 1: RD-on (High complexity mode)
                              # 2: RD-on (Fast high complexity mode - not work in FREX Profiles)
                              # 3: with losses
+DistortionSSIM         =  0  # Compute SSIM distortion. (0: disabled/default, 1: enabled)
+SSIMOverlapSize        =  8  # Overlap size to calculate SSIM distortion (1: pixel by pixel, 8: no overlap)
+DistortionYUVtoRGB     =  0  # Calculate distortion in RGB domain after conversion from YCbCr (0:off, 1:on)
 CtxAdptLagrangeMult    =  0  # Context Adaptive Lagrange Multiplier
                              # 0: disabled (default)
                              # 1: enabled (works best when RDOptimization=0)
@@ -266,19 +289,21 @@ WeightCr               =  1  # Cr weight for RDO
 # Explicit Lambda Usage
 ##########################################################################################
 UseExplicitLambdaParams  =  0    # Use explicit lambda scaling parameters (0:disabled, 1:enable lambda weight, 2: use explicit lambda value)
-FixedLambdaISlice        =  0.1  # Fixed Lambda value for I slices
-FixedLambdaPSlice        =  0.1  # Fixed Lambda value for P slices
-FixedLambdaBSlice        =  0.1  # Fixed Lambda value for B slices
-FixedLambdaRefBSlice     =  0.1  # Fixed Lambda value for Referenced B slices
-FixedLambdaSPSlice       =  0.1  # Fixed Lambda value for SP slices
-FixedLambdaSISlice       =  0.1  # Fixed Lambda value for SI slices
-
-LambdaWeightISlice       =  0.65 # scaling param for I slices. This will be used as a multiplier i.e. lambda=LambdaWeightISlice * 2^((QP-12)/3)
-LambdaWeightPSlice       =  0.68 # scaling param for P slices. This will be used as a multiplier i.e. lambda=LambdaWeightPSlice * 2^((QP-12)/3)
-LambdaWeightBSlice       =  0.68 # scaling param for B slices. This will be used as a multiplier i.e. lambda=LambdaWeightBSlice * 2^((QP-12)/3)
-LambdaWeightRefBSlice    =  0.68 # scaling param for Referenced B slices. This will be used as a multiplier i.e. lambda=LambdaWeightRefBSlice * 2^((QP-12)/3)
-LambdaWeightSPSlice      =  0.68 # scaling param for SP slices. This will be used as a multiplier i.e. lambda=LambdaWeightSPSlice * 2^((QP-12)/3)
-LambdaWeightSISlice      =  0.65 # scaling param for SI slices. This will be used as a multiplier i.e. lambda=LambdaWeightSISlice * 2^((QP-12)/3)
+UpdateLambdaChromaME     =  0    # Update lambda given Chroma ME consideration
+FixedLambdaIslice        =  0.1  # Fixed Lambda value for I slices
+FixedLambdaPslice        =  0.1  # Fixed Lambda value for P slices
+FixedLambdaBslice        =  0.1  # Fixed Lambda value for B slices
+FixedLambdaRefBslice     =  0.1  # Fixed Lambda value for Referenced B slices
+FixedLambdaSPslice       =  0.1  # Fixed Lambda value for SP slices
+FixedLambdaSIslice       =  0.1  # Fixed Lambda value for SI slices
+
+LambdaWeightIslice       =  0.65 # scaling param for I slices. This will be used as a multiplier i.e. lambda=LambdaWeightISlice * 2^((QP-12)/3)
+LambdaWeightPslice       =  0.68 # scaling param for P slices. This will be used as a multiplier i.e. lambda=LambdaWeightPSlice * 2^((QP-12)/3)
+LambdaWeightBslice       =  0.68 # scaling param for B slices. This will be used as a multiplier i.e. lambda=LambdaWeightBSlice * 2^((QP-12)/3)
+LambdaWeightRefBslice    =  0.68 # scaling param for Referenced B slices. This will be used as a multiplier i.e. lambda=LambdaWeightRefBSlice * 2^((QP-12)/3)
+LambdaWeightSPslice      =  0.68 # scaling param for SP slices. This will be used as a multiplier i.e. lambda=LambdaWeightSPSlice * 2^((QP-12)/3)
+LambdaWeightSIslice      =  0.65 # scaling param for SI slices. This will be used as a multiplier i.e. lambda=LambdaWeightSISlice * 2^((QP-12)/3)
+
 
 LossRateA                =  5  # expected packet loss rate of the channel for the first partition, only valid if RDOptimization = 3
 LossRateB                =  0  # expected packet loss rate of the channel for the second partition, only valid if RDOptimization = 3
@@ -302,7 +327,7 @@ NumberofLeakyBuckets     =  8                      # Number of Leaky Bucket valu
 LeakyBucketRateFile      =  "leakybucketrate.cfg"  # File from which encoder derives rate values
 LeakyBucketParamFile     =  "leakybucketparam.cfg" # File where encoder stores leakybucketparams
 
-NumberFramesInEnhancementLayerSubSequence  = 0  # number of frames in the Enhanced Scalability Layer(0: no Enhanced Layer)
+NumFramesInELayerSubSeq  = 0  # number of frames in the Enhanced Scalability Layer(0: no Enhanced Layer)
 
 SparePictureOption        =  0   # (0: no spare picture info, 1: spare picture available)
 SparePictureDetectionThr  =  6   # Threshold for spare reference pictures detection
@@ -319,7 +344,7 @@ Bitrate                 = 45020 # Bitrate(bps)
 InitialQP               = 0     # Initial Quantization Parameter for the first I frame
                                 # InitialQp depends on two values: Bits Per Picture,
                                 # and the GOP length
-BasicUnit               = 1     # Number of basic units in the frame
+BasicUnit               = 11    # Number of MBs in the basic unit
                                 # should be a fraction of the total number
                                 # of MBs in a frame
 ChannelType             = 0     # type of channel( 1=time varying channel; 0=Constant channel)
@@ -338,7 +363,7 @@ RCBSliceBitRatio4       = 0.25  # target ratio of bits for B-coded pictures comp
 RCBoverPRatio           = 0.45  # ratio of bit rate usage of a B-coded picture over a P-coded picture for the SAME QP (for RCUpdateMode=3)
 RCIoverPRatio           = 3.80  # ratio of bit rate usage of an I-coded picture over a P-coded picture for the SAME QP (for RCUpdateMode=3)
 RCMinQPPSlice           =  8    # minimum P Slice QP value for rate control
-RCMaxQPPSlice           = 40    # maximum P Slice QP value for rate control
+RCMaxQPPSlice           = 44    # maximum P Slice QP value for rate control
 RCMinQPBSlice           =  8    # minimum B Slice QP value for rate control
 RCMaxQPBSlice           = 46    # maximum B Slice QP value for rate control
 RCMinQPISlice           =  8    # minimum I Slice QP value for rate control
@@ -441,8 +466,12 @@ QPPrimeYZeroTransformBypassFlag = 0    # Enable lossless coding when qpprime_y i
 #Fast Motion Estimation Control Parameters
 ########################################################################################
 
-SearchMode               = 0    # Use fast motion estimation (0=disable/default, 1=UMHexagonS, 
-                                # 2=Simplified UMHexagonS, 3=EPZS patterns)
+SearchMode               = 0    # Motion estimation mode
+                                # -1 = Full Search
+                                #  0 = Fast Full Search (default)
+                                #  1 = UMHexagon Search
+                                #  2 = Simplified UMHexagon Search
+                                #  3 = Enhanced Predictive Zonal Search (EPZS)
 UMHexDSR                 = 1    # Use Search Range Prediction. Only for UMHexagonS method
                                 # (0:disable, 1:enabled/default)
 UMHexScale               = 3    # Use Scale_factor for different image sizes. Only for UMHexagonS method
@@ -463,6 +492,8 @@ EPZSTemporal             = 1    # Enables temporal predictors
                                 # (0: disabled, 1: enabled/default)
 EPZSSpatialMem           = 1    # Enables spatial memory predictors
                                 # (0: disabled, 1: enabled/default)
+EPZSBlockType            = 1    # Enables block type Predictors
+                                # (0: disabled, 1: enabled/default)
 EPZSMinThresScale        = 0    # Scaler for EPZS minimum threshold (0 default).
                                 # Increasing value can speed up encoding.
 EPZSMedThresScale        = 1    # Scaler for EPZS median threshold (1 default).
diff --git a/bin/encoder_yuv422.cfg b/bin/encoder_yuv422.cfg
index 784f216..0277e4a 100644
--- a/bin/encoder_yuv422.cfg
+++ b/bin/encoder_yuv422.cfg
@@ -15,11 +15,16 @@ InputHeaderLength     = 0      # If the inputfile has a header, state it's lengt
 StartFrame            = 0      # Start frame for encoding. (0-N)
 FramesToBeEncoded     = 2      # Number of frames to be coded
 FrameRate             = 30.0   # Frame Rate per second (0.1-100.0)
-SourceWidth           = 176    # Frame width
-SourceHeight          = 144    # Frame height
+SourceWidth           = 176    # Source frame width
+SourceHeight          = 144    # Source frame height
+SourceResize          = 0      # Resize source size for output
+OutputWidth           = 176    # Output frame width
+OutputHeight          = 144    # Output frame height
+
 TraceFile             = "trace_enc.txt"      # Trace file 
 ReconFile             = "test_rec.yuv"       # Recontruction YUV file
 OutputFile            = "test.264"           # Bitstream
+StatsFile             = "stats.dat"          # Coding statistics file
 
 ##########################################################################################
 # Encoder Control
@@ -52,7 +57,10 @@ ChromaMCBuffer        = 1   # Calculate Color component interpolated values in a
                             # Provides a trade-off between memory and computational complexity
                             # (0: disabled/default, 1: enabled)
 ChromaMEEnable        = 0   # Take into account Color component information during ME
-                            # (0: only first component/default, 1: All Color components)
+                            # (0: only first component/default, 
+                            #  1: All Color components - Integer refinement only
+                            #  2: All Color components - All refinements)
+ChromaMEWeight        = 1   # Weighting for chroma components. This parameter should have a relationship with color format.
 
 NumberReferenceFrames = 5   # Number of previous frames used for inter motion search (0-16)
 
@@ -82,6 +90,8 @@ BSliceSearch8x4       = 1   # B-Slice Inter block search  8x4  (0=disable, 1=ena
 BSliceSearch4x8       = 1   # B-Slice Inter block search  4x8  (0=disable, 1=enable)
 BSliceSearch4x4       = 1   # B-Slice Inter block search  4x4  (0=disable, 1=enable)
 
+DisableIntra4x4        = 0  # Disable Intra 4x4 mode
+DisableIntra16x16      = 0  # Disable Intra 16x16 mode
 DisableIntraInInter    = 0  # Disable Intra modes for inter slices
 IntraDisableInterOnly  = 0  # Apply Disabling Intra conditions only to Inter Slices (0:disable/default,1: enable)
 Intra4x4ParDisable     = 0  # Disable Vertical & Horizontal 4x4
@@ -180,9 +190,11 @@ RDPictureDecision        =  0     # Perform RD optimal decision between differen
 RDPictureIntra           =  0     # Perform RD optimal decision also for intra coded pictures (0: disabled (default), 1: enabled).
 RDPSliceWeightOnly       =  1     # Only consider Weighted Prediction for P slices in Picture RD decision. (0: disabled, 1: enabled (default))
 RDBSliceWeightOnly       =  0     # Only consider Weighted Prediction for B slices in Picture RD decision. (0: disabled (default), 1: enabled )
+RDPSliceBTest            =  1     # Perform Slice level RD decision between P and P slices. 
+                                  # Requires RDPSliceWeightOnly = 0. (0: disabled (default), 1: enabled )
 
 ##########################################################################################
-# Loop filter parameters
+# Deblocking filter parameters
 ##########################################################################################
 
 DFParametersFlag         = 0      # Configure deblocking filter (0=parameters below ignored, 1=parameters sent)
@@ -290,7 +302,7 @@ NumberofLeakyBuckets     =  8                      # Number of Leaky Bucket valu
 LeakyBucketRateFile      =  "leakybucketrate.cfg"  # File from which encoder derives rate values
 LeakyBucketParamFile     =  "leakybucketparam.cfg" # File where encoder stores leakybucketparams
 
-NumberFramesInEnhancementLayerSubSequence  = 0  # number of frames in the Enhanced Scalability Layer(0: no Enhanced Layer)
+NumFramesInELayerSubSeq  = 0  # number of frames in the Enhanced Scalability Layer(0: no Enhanced Layer)
 
 SparePictureOption        =  0   # (0: no spare picture info, 1: spare picture available)
 SparePictureDetectionThr  =  6   # Threshold for spare reference pictures detection
@@ -307,8 +319,8 @@ Bitrate                 = 45020 # Bitrate(bps)
 InitialQP               = 0     # Initial Quantization Parameter for the first I frame
                                 # InitialQp depends on two values: Bits Per Picture,
                                 # and the GOP length
-BasicUnit               = 11    # Number of MBs in the basic unit
-                                # should be a fractor of the total number
+BasicUnit               = 1     # Number of basic units in the frame
+                                # should be a fraction of the total number
                                 # of MBs in a frame
 ChannelType             = 0     # type of channel( 1=time varying channel; 0=Constant channel)
 RCUpdateMode            = 0     # Rate Control type. Modes supported :
@@ -326,7 +338,7 @@ RCBSliceBitRatio4       = 0.25  # target ratio of bits for B-coded pictures comp
 RCBoverPRatio           = 0.45  # ratio of bit rate usage of a B-coded picture over a P-coded picture for the SAME QP (for RCUpdateMode=3)
 RCIoverPRatio           = 3.80  # ratio of bit rate usage of an I-coded picture over a P-coded picture for the SAME QP (for RCUpdateMode=3)
 RCMinQPPSlice           =  8    # minimum P Slice QP value for rate control
-RCMaxQPPSlice           = 40    # maximum P Slice QP value for rate control
+RCMaxQPPSlice           = 44    # maximum P Slice QP value for rate control
 RCMinQPBSlice           =  8    # minimum B Slice QP value for rate control
 RCMaxQPBSlice           = 46    # maximum B Slice QP value for rate control
 RCMinQPISlice           =  8    # minimum I Slice QP value for rate control
@@ -335,6 +347,7 @@ RCMinQPSPSlice          =  8    # minimum SP Slice QP value for rate control
 RCMaxQPSPSlice          = 40    # maximum SP Slice QP value for rate control
 RCMinQPSISlice          =  8    # minimum SI Slice QP value for rate control
 RCMaxQPSISlice          = 36    # maximum SI Slice QP value for rate control
+RCMaxQPChange           =  4    # maximum QP change for frames of the base layer
 
 ########################################################################################
 #Fast Mode Decision
@@ -349,8 +362,12 @@ SelectiveIntraEnable    = 0     # Selective Intra mode decision (0: Disable 1: E
 YUVFormat               = 2     # YUV format (0=4:0:0, 1=4:2:0, 2=4:2:2, 3=4:4:4)
 RGBInput                = 0     # 1=RGB input, 0=GBR or YUV input
 SeparateColourPlane     = 0     # 4:4:4 coding: 0=Common mode, 1=Independent mode
-BitDepthLuma            = 8     # Bit Depth for Luminance (8...12 bits)
-BitDepthChroma          = 8     # Bit Depth for Chrominance (8...12 bits)
+SourceBitDepthLuma      = 8     # Source Bit Depth for Luma color component (8...14 bits)
+SourceBitDepthChroma    = 8     # Source Bit Depth for Chroma color components (8...14 bits)
+SourceBitDepthRescale   = 0     # Rescale bit depth of source for output (0: Disable 1: Enable)
+OutputBitDepthLuma      = 8     # Output Bit Depth for Luma color component (8...14 bits)
+OutputBitDepthChroma    = 8     # Output Bit Depth for Chroma color components (8...14 bits)
+
 CbQPOffset              = 0     # Chroma QP offset for Cb-part (-51..51)
 CrQPOffset              = 0     # Chroma QP offset for Cr-part (-51..51)
 Transform8x8Mode        = 1     # (0: only 4x4 transform, 1: allow using 8x8 transform additionally, 2: only 8x8 transform)
@@ -381,12 +398,12 @@ ScalingListPresentFlag11 = 3    # Inter8x8_ChromaV for 4:4:4 (0 Not present, 1 P
 #Rounding Offset control
 ########################################################################################
 
-OffsetMatrixPresentFlag  = 0    # Enable Explicit Offset Quantization Matrices  (0: disable 1: enable)
+OffsetMatrixPresentFlag  = 1    # Enable Explicit Offset Quantization Matrices  (0: disable 1: enable)
 QOffsetMatrixFile        = "q_offset.cfg" # Explicit Quantization Matrices file
 
-AdaptiveRounding         = 1   # Enable Adaptive Rounding based on JVT-N011 (0: disable, 1: enable)
+AdaptiveRounding         = 1    # Enable Adaptive Rounding based on JVT-N011 (0: disable, 1: enable)
 AdaptRoundingFixed       = 1    # Enable Global Adaptive rounding for all qps (0: disable, 1: enable - default/old)
-AdaptRndPeriod           = 1    # Period in terms of MBs for updating rounding offsets.
+AdaptRndPeriod           = 16   # Period in terms of MBs for updating rounding offsets. 
                                 # 0 performs update at the picture level. Default is 16. 1 is as in JVT-N011.
 AdaptRndChroma           = 1    # Enables coefficient rounding adaptation for chroma
 
@@ -404,6 +421,16 @@ AdaptRndCrWFactorINRef   = 4    # Chroma Adaptive Rounding Weight for I/SI slice
 AdaptRndCrWFactorPNRef   = 4    # Chroma Adaptive Rounding Weight for P/SP slices in non reference pictures /4096
 AdaptRndCrWFactorBNRef   = 4    # Chroma Adaptive Rounding Weight for B slices in non reference pictures /4096
 
+################################################################
+# Rate Distortion Optimized Quantization
+################################################################
+UseRDOQuant              =  0 # Use Rate Distortion Optimized Quantization (0=disable, 1=enable)
+RDOQ_CR                  =  0 # Enable Rate Distortion Optimized Quantization for Chroma components (0=disable, 1=enable)
+RDOQ_QP_Num              =  1 # 1-5: Number of QP tested in RDO_Q (I/P/B slice)
+RDOQ_CP_Mode             =  1 # copy Mode from first QP tested
+RDOQ_CP_MV               =  0 # copy MV from first QP tested
+RDOQ_Fast                =  0 # Fast RDOQ decision method for multiple QPs
+
 ########################################################################################
 #Lossless Coding (FREXT)
 ########################################################################################
@@ -414,8 +441,12 @@ QPPrimeYZeroTransformBypassFlag = 0    # Enable lossless coding when qpprime_y i
 #Fast Motion Estimation Control Parameters
 ########################################################################################
 
-SearchMode               = 0    # Use fast motion estimation (0=disable/default, 1=UMHexagonS,
-                                # 2=Simplified UMHexagonS, 3=EPZS patterns)
+SearchMode               = 0    # Motion estimation mode
+                                # -1 = Full Search
+                                #  0 = Fast Full Search (default)
+                                #  1 = UMHexagon Search
+                                #  2 = Simplified UMHexagon Search
+                                #  3 = Enhanced Predictive Zonal Search (EPZS)
 UMHexDSR                 = 1    # Use Search Range Prediction. Only for UMHexagonS method
                                 # (0:disable, 1:enabled/default)
 UMHexScale               = 3    # Use Scale_factor for different image sizes. Only for UMHexagonS method
@@ -445,7 +476,7 @@ EPZSMaxThresScale        = 2    # Scaler for EPZS maximum threshold (1 default).
 EPZSSubPelME             = 1    # EPZS Subpel ME consideration
 EPZSSubPelMEBiPred       = 1    # EPZS Subpel ME consideration for BiPred partitions
 EPZSSubPelThresScale     = 2    # EPZS Subpel ME Threshold scaler
-EPZSSubPelGrid           = 0    # Perform EPZS using a subpixel grid
+EPZSSubPelGrid           = 1    # Perform EPZS using a subpixel grid
 
 ########################################################################################
 # SEI Parameters
@@ -465,6 +496,7 @@ SEIMessageText            = "H.264/AVC Encoder"  # Text SEI Message
 
 EnableVUISupport                                = 0      # Enable VUI Parameters
 
+# display parameters
 VUI_aspect_ratio_info_present_flag              = 0
 VUI_aspect_ratio_idc                            = 1
 VUI_sar_width                                   = 0
@@ -487,40 +519,40 @@ VUI_time_scale                                  = 60000
 VUI_fixed_frame_rate_flag                       = 0
 
 # nal hrd parameters
-VUI_nal_hrd_parameters_present_flag      = 0
-VUI_nal_cpb_cnt_minus1                   = 0
-VUI_nal_bit_rate_scale                   = 0
-VUI_nal_cpb_size_scale                   = 0
-VUI_nal_bit_rate_value_minus1            = 0
-VUI_nal_cpb_size_value_minus1            = 0
-VUI_nal_vbr_cbr_flag                     = 0
+VUI_nal_hrd_parameters_present_flag             = 0
+VUI_nal_cpb_cnt_minus1                          = 0
+VUI_nal_bit_rate_scale                          = 0
+VUI_nal_cpb_size_scale                          = 0
+VUI_nal_bit_rate_value_minus1                   = 0
+VUI_nal_cpb_size_value_minus1                   = 0
+VUI_nal_vbr_cbr_flag                            = 0
 VUI_nal_initial_cpb_removal_delay_length_minus1 = 23
 VUI_nal_cpb_removal_delay_length_minus1         = 23
 VUI_nal_dpb_output_delay_length_minus1          = 23
 VUI_nal_time_offset_length                      = 24
 
 # vlc hrd parameters
-VUI_vcl_hrd_parameters_present_flag      = 0
-VUI_vcl_cpb_cnt_minus1                   = 0
-VUI_vcl_bit_rate_scale                   = 0
-VUI_vcl_cpb_size_scale                   = 0
-VUI_vcl_bit_rate_value_minus1            = 0
-VUI_vcl_cpb_size_value_minus1            = 0
-VUI_vcl_vbr_cbr_flag                     = 0
+VUI_vcl_hrd_parameters_present_flag             = 0
+VUI_vcl_cpb_cnt_minus1                          = 0
+VUI_vcl_bit_rate_scale                          = 0
+VUI_vcl_cpb_size_scale                          = 0
+VUI_vcl_bit_rate_value_minus1                   = 0
+VUI_vcl_cpb_size_value_minus1                   = 0
+VUI_vcl_vbr_cbr_flag                            = 0
 VUI_vcl_initial_cpb_removal_delay_length_minus1 = 23
 VUI_vcl_cpb_removal_delay_length_minus1         = 23
 VUI_vcl_dpb_output_delay_length_minus1          = 23
 VUI_vcl_time_offset_length                      = 24
-VUI_low_delay_hrd_flag                      = 0
+VUI_low_delay_hrd_flag                          = 0
 
 # other params (i.e. bitsream restrictions)
-VUI_pic_struct_present_flag                 = 0
-VUI_bitstream_restriction_flag              = 0
-VUI_motion_vectors_over_pic_boundaries_flag = 1
-VUI_max_bytes_per_pic_denom                 = 0
-VUI_max_bits_per_mb_denom                   = 0
-VUI_log2_max_mv_length_vertical             = 16
-VUI_log2_max_mv_length_horizontal           = 16
-VUI_num_reorder_frames                      = 16
-VUI_max_dec_frame_buffering                 = 16
+VUI_pic_struct_present_flag                     = 0
+VUI_bitstream_restriction_flag                  = 0
+VUI_motion_vectors_over_pic_boundaries_flag     = 1
+VUI_max_bytes_per_pic_denom                     = 0
+VUI_max_bits_per_mb_denom                       = 0
+VUI_log2_max_mv_length_vertical                 = 16
+VUI_log2_max_mv_length_horizontal               = 16
+VUI_num_reorder_frames                          = 16
+VUI_max_dec_frame_buffering                     = 16
 
diff --git a/doc/ldecod.dox b/doc/ldecod.dox
index 7ae0346..9410356 100644
--- a/doc/ldecod.dox
+++ b/doc/ldecod.dox
@@ -7,7 +7,7 @@ DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "H.264/AVC Reference Software Decoder "
 PROJECT_NUMBER         = 
 OUTPUT_DIRECTORY       = ./ldec
-CREATE_SUBDIRS         = YES
+CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
 BRIEF_MEMBER_DESC      = NO
 REPEAT_BRIEF           = YES
diff --git a/doc/lencod.dox b/doc/lencod.dox
index 5ed682f..5dc70ff 100644
--- a/doc/lencod.dox
+++ b/doc/lencod.dox
@@ -7,7 +7,7 @@ DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "H.264/AVC Reference Software Encoder "
 PROJECT_NUMBER         = 
 OUTPUT_DIRECTORY       = ./lenc
-CREATE_SUBDIRS         = YES
+CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
 BRIEF_MEMBER_DESC      = NO
 REPEAT_BRIEF           = YES
diff --git a/ldecod/inc/annexb.h b/ldecod/inc/annexb.h
index dcfe648..8ad83a7 100644
--- a/ldecod/inc/annexb.h
+++ b/ldecod/inc/annexb.h
@@ -18,7 +18,7 @@ extern int IsFirstByteStreamNALU;
 extern int LastAccessUnitExists;
 extern int NALUCount;
 
-int  GetAnnexbNALU (NALU_t *nalu);
+int  GetAnnexbNALU (FILE *bitstream, NALU_t *nalu);
 void OpenBitstreamFile (char *fn);
 void CloseBitstreamFile(void);
 void CheckZeroByteNonVCL(NALU_t *nalu);
diff --git a/ldecod/inc/block.h b/ldecod/inc/block.h
index 72653fc..e77ac77 100644
--- a/ldecod/inc/block.h
+++ b/ldecod/inc/block.h
@@ -20,28 +20,25 @@
 
 #include "global.h"
 
-#define DQ_BITS         6
-
 extern const byte QP_SCALE_CR[52] ;
-extern const int  dequant_coef[6][4][4];
 extern const unsigned char subblk_offset_x[3][8][4];
 extern const unsigned char subblk_offset_y[3][8][4];
 extern void iMBtrans4x4(ColorPlane pl, ImageParameters *img, int smb);
-extern void iMBtrans8x8(ColorPlane pl, ImageParameters *img);
+extern void iMBtrans8x8(ImageParameters *img,  Macroblock *currMB, ColorPlane pl);
 
 extern void itrans_sp_cr(ImageParameters *img, int uv);
-void (*itrans_4x4)(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-void (*itrans_8x8)(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-
-extern void Inv_Residual_trans_4x4(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-extern void Inv_Residual_trans_8x8(ColorPlane pl, ImageParameters *img, int ioff,int joff);
-
-extern void itrans8x8(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-extern void itrans4x4(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-extern void itrans4x4_ls(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-extern void itrans_sp(ColorPlane pl, ImageParameters *img, int ioff, int joff);
-extern int  intrapred(Macroblock *currMB, ColorPlane pl, ImageParameters *img,int ioff,int joff,int i4,int j4);
-extern void itrans_2 (ColorPlane pl, ImageParameters *img);
-extern void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img, int need_4x4_transform, int smb);
+void (*itrans_4x4)(ImageParameters *img, ColorPlane pl, int ioff, int joff);
+void (*itrans_8x8)(ImageParameters *img, Macroblock *currMB, ColorPlane pl, int ioff, int joff);
+
+extern void Inv_Residual_trans_4x4(ImageParameters *img, ColorPlane pl, int ioff, int joff);
+extern void Inv_Residual_trans_8x8(ImageParameters *img, Macroblock *currMB, ColorPlane pl, int ioff,int joff);
+
+extern void itrans8x8   (ImageParameters *img, Macroblock *currMB, ColorPlane pl, int ioff, int joff);
+extern void itrans4x4   (ImageParameters *img, ColorPlane pl, int ioff, int joff);
+extern void itrans4x4_ls(ImageParameters *img, ColorPlane pl, int ioff, int joff);
+extern void itrans_sp   (ImageParameters *img, ColorPlane pl, int ioff, int joff);
+extern int  intrapred   (ImageParameters *img, Macroblock *currMB, ColorPlane pl, int ioff,int joff,int i4,int j4);
+extern void itrans_2    (ImageParameters *img, Macroblock *currMB, ColorPlane pl);
+extern void iTransform  (ImageParameters *img, Macroblock *currMB, ColorPlane pl, int need_4x4_transform, int smb);
 #endif
 
diff --git a/ldecod/inc/global.h b/ldecod/inc/global.h
index c91cbec..d0a8f67 100644
--- a/ldecod/inc/global.h
+++ b/ldecod/inc/global.h
@@ -66,20 +66,6 @@ int  g_nFrame;
 int  TopFieldForSkip_Y[16][16];
 int  TopFieldForSkip_UV[2][16][16];
 
-int  InvLevelScale4x4Luma_Intra[6][4][4];
-int  InvLevelScale4x4Chroma_Intra[2][6][4][4];
-
-int  InvLevelScale4x4Luma_Inter[6][4][4];
-int  InvLevelScale4x4Chroma_Inter[2][6][4][4];
-
-int  InvLevelScale8x8Luma_Intra[6][8][8];
-int  InvLevelScale8x8Chroma_Intra[2][6][8][8];
-
-int  InvLevelScale8x8Luma_Inter[6][8][8];
-int  InvLevelScale8x8Chroma_Inter[2][6][8][8];
-
-int  *qmatrix[12];
-
 #define ET_SIZE 300      //!< size of error text buffer
 char errortext[ET_SIZE]; //!< buffer for error message for exit with error()
 
@@ -140,17 +126,17 @@ typedef enum
 
 typedef enum
 {
-  BITS_HEADER,
-  BITS_TOTAL_MB,
-  BITS_MB_MODE,
-  BITS_INTER_MB,
-  BITS_CBP_MB,
-  BITS_COEFF_Y_MB,
-  BITS_COEFF_UV_MB,
-  BITS_COEFF_CB_MB,  
-  BITS_COEFF_CR_MB,
-  BITS_DELTA_QUANT_MB,
-  MAX_BITCOUNTER_MB
+  BITS_HEADER         = 0,
+  BITS_TOTAL_MB       = 1,
+  BITS_MB_MODE        = 2,
+  BITS_INTER_MB       = 3,
+  BITS_CBP_MB         = 4,
+  BITS_COEFF_Y_MB     = 5,
+  BITS_COEFF_CB_MB    = 6,  
+  BITS_COEFF_CR_MB    = 7,
+  BITS_DELTA_QUANT_MB = 8,
+  BITS_STUFFING       = 9,
+  MAX_BITCOUNTER_MB   = 10
 } BitCountType;
 
 typedef enum 
@@ -343,8 +329,9 @@ typedef struct syntaxelement
 //! Macroblock
 typedef struct macroblock
 {
-  int           qp;                  //!< QP luma
-  int           qpc[2];              //!< QP chroma
+  int           qp;                    //!< QP luma
+  int           qpc[2];                //!< QP chroma
+  int           qp_scaled[MAX_PLANE];  //!< QP scaled for all comps.
 
   int           slice_nr;
   int           delta_quant;          //!< for rate control
@@ -417,6 +404,8 @@ typedef struct
   int                 ei_flag;       //!< 0 if the partArr[0] contains valid information
   int                 qp;
   int                 slice_qp_delta;
+  int                 qs;
+  int                 slice_qs_delta;
   int                 picture_type;  //!< picture type
   PictureStructure    structure;     //!< Identify picture structure type
   int                 start_mb_nr;   //!< MUST be set by NAL even in case of ei_flag == 1
@@ -484,20 +473,20 @@ typedef struct img_par
   
   int mvscale[6][MAX_REFERENCE_PICTURES];
 
-  imgpel mpr[MAX_PLANE][16][16];     //!< predicted block
-  int    m7 [MAX_PLANE][16][16];     //!< residual macroblock
+  imgpel mb_pred[MAX_PLANE][16][16];     //!< predicted block
+  int    mb_rres[MAX_PLANE][16][16];     //!< residual macroblock
   int    cof[MAX_PLANE][16][16];     //!< transformed coefficients 
+  int    fcf[MAX_PLANE][16][16];     //!< transformed coefficients 
   
   int cofu[16];
   byte **ipredmode;                  //!< prediction type [90][74]
-  int ***nz_coeff;
+  int ****nz_coeff;
   int **siblock;
   int cod_counter;                   //!< Current count of number of skipped macroblocks in a row
 
   int newframe;
 
   int structure;                     //!< Identify picture structure type
-  int pstruct_next_P;
 
   // B pictures
   Slice      *currentSlice;          //!< pointer to current Slice data struct
@@ -603,8 +592,6 @@ typedef struct img_par
   int bitdepth_luma_qp_scale;
   int bitdepth_chroma_qp_scale;
   unsigned int dc_pred_value_comp[MAX_PLANE]; //!< component value for DC prediction (depends on component pel bit depth)
-  int max_imgpel_value;                       //!< max value that one luma picture element (pixel) can take (depends on pic_unit_bitdepth)
-  int max_imgpel_value_uv;                    //!< max value that one chroma picture element (pixel) can take (depends on pic_unit_bitdepth)
   int max_imgpel_value_comp[MAX_PLANE];       //!< max value that one picture element (pixel) can take (depends on pic_unit_bitdepth)
   int Transform8x8Mode;
   int profile_idc;
@@ -620,20 +607,18 @@ typedef struct img_par
   int mb_size[3][2];                         //!< component macroblock dimensions
   int mb_size_blk[3][2];                     //!< component macroblock dimensions 
   int mb_size_shift[3][2];
+  
+  int max_vmv_r;                             //!< maximum vertical motion vector range in luma quarter frame pixel units for the current level_idc
+  int max_mb_vmv_r;                          //!< maximum vertical motion vector range in luma quarter pixel units for the current level_idc
 
   int idr_psnr_number;
   int psnr_number;
 
-  time_t ltime_start;               // for time measurement
-  time_t ltime_end;                 // for time measurement
-
-#ifdef WIN32
-  struct _timeb tstruct_start;
-  struct _timeb tstruct_end;
-#else
-  struct timeb tstruct_start;
-  struct timeb tstruct_end;
-#endif
+  // Timing related variables
+  struct TIMEB tstruct_start;
+  struct TIMEB tstruct_end;
+  time_t ltime_start;               
+  time_t ltime_end;                 
 
   // picture error concealment
   int last_ref_pic_poc;
@@ -653,7 +638,6 @@ typedef struct img_par
   int recovery_poc;
 
   int  separate_colour_plane_flag;
-
 } ImageParameters;
 
 extern ImageParameters *img;
@@ -696,7 +680,6 @@ struct inp_par
   int conceal_mode;
   int ref_poc_gap;
   int poc_gap;
-
 };
 
 extern struct inp_par *params;
@@ -760,36 +743,27 @@ void init_picture(ImageParameters *img, struct inp_par *inp);
 void exit_picture(void);
 
 int  read_new_slice(void);
-void decode_one_slice(ImageParameters *img,struct inp_par *inp);
-
-void start_macroblock(Macroblock **currMB, ImageParameters *img);
-void read_one_macroblock(Macroblock *currMB, ImageParameters *img);
-void read_ipred_modes(Macroblock *currMB, ImageParameters *img);
-int  decode_one_macroblock(Macroblock *currMB, ImageParameters *img);
-Boolean  exit_macroblock(ImageParameters *img,int eos_bit);
-void decode_ipcm_mb(Macroblock *currMB, ImageParameters *img);
+void decode_one_slice(ImageParameters *img, struct inp_par *inp);
 
+void start_macroblock     (ImageParameters *img, Macroblock **currMB);
+void read_one_macroblock  (ImageParameters *img, Macroblock *currMB);
+Boolean  exit_macroblock  (ImageParameters *img, int eos_bit);
+void concealIPCMcoeffs    (ImageParameters *img);
 
-void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img);
-void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img);
-void concealIPCMcoeffs(ImageParameters *img);
-void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP);
-void SetMotionVectorPredictor (Macroblock *currMB, ImageParameters  *img, short pmv[2], char ref_frame, byte list, 
+void SetMotionVectorPredictor (ImageParameters  *img, Macroblock *currMB, short pmv[2], char ref_frame, byte list, 
                                char ***refPic, short ****tmp_mv, 
                                int mb_x, int mb_y, int blockshape_x, int blockshape_y);
 
-void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters *img, int b8);
 
-void copyblock_sp(ImageParameters *img,int block_x,int block_y);
-int  intrapred_luma_16x16(Macroblock *currMB, ColorPlane pl, ImageParameters *img,int predmode);
-void intrapred_chroma(Macroblock *currMB, ImageParameters *img, int uv);
+int  intrapred_luma_16x16(ImageParameters *img, Macroblock *currMB, ColorPlane pl, int predmode);
+void intrapred_chroma    (ImageParameters *img, Macroblock *currMB, int uv);
 
 // SLICE function pointers
-int  (*nal_startcode_follows) (ImageParameters*, int );
+int  (*nal_startcode_follows) (Slice*, int );
 
 // NAL functions TML/CABAC bitstream
-int  uvlc_startcode_follows(ImageParameters *img, int dummy);
-int  cabac_startcode_follows(ImageParameters *img, int eos_bit);
+int  uvlc_startcode_follows(Slice *currSlice, int dummy);
+int  cabac_startcode_follows(Slice *currSlice, int eos_bit);
 void free_Partition(Bitstream *currStream);
 
 // ErrorConcealment
@@ -827,11 +801,6 @@ void readIPCM_CABAC(struct datapartition *dP);
 unsigned CeilLog2( unsigned uiVal);
 unsigned CeilLog2_sf( unsigned uiVal);
 
-// For Q-matrix
-void AssignQuantParam(pic_parameter_set_rbsp_t* pps, seq_parameter_set_rbsp_t* sps);
-void CalculateQuantParam(void);
-void CalculateQuant8Param(void);
-
 //For residual DPCM
 int ipmode_DPCM;
 
@@ -839,12 +808,6 @@ int ipmode_DPCM;
 void change_plane_JV( int nplane );
 void make_frame_picture_JV(void);
 
-// Interpret MB mode
-void (*interpret_mb_mode)(Macroblock *currMB);
-void interpret_mb_mode_P(Macroblock *currMB);
-void interpret_mb_mode_B(Macroblock *currMB);
-void interpret_mb_mode_I(Macroblock *currMB);
-void interpret_mb_mode_SI(Macroblock *currMB);
 #endif
 
 
diff --git a/ldecod/inc/ifunctions.h b/ldecod/inc/ifunctions.h
index db5a60e..abaf5c6 100644
--- a/ldecod/inc/ifunctions.h
+++ b/ldecod/inc/ifunctions.h
@@ -21,6 +21,7 @@
   #define static
   #define inline
 #endif
+#include <math.h>
 
 static inline int imin(int a, int b)
 {
@@ -141,11 +142,29 @@ static inline int RSD(int x)
  return ((x&2)?(x|1):(x&(~1)));
 }
 
+static inline int power2(int x) 
+{
+  return 1 << (x);
+}
+
 static inline int float2int (float x)
 {
   return (int)((x < 0) ? (x - 0.5f) : (x + 0.5f));
 }
 
+#if ZEROSNR
+static inline float psnr(int max_sample_sq, int samples, float sse_distortion ) 
+{
+  return (float) (10.0 * log10(max_sample_sq * (double) ((double) samples / (sse_distortion == 0.0 ? 1.0 : sse_distortion))));
+}
+#else
+static inline float psnr(int max_sample_sq, int samples, float sse_distortion ) 
+{
+  return (float) (sse_distortion == 0.0 ? 0.0 : (10.0 * log10(max_sample_sq * (double) ((double) samples / sse_distortion))));
+}
+#endif
+
+
 # if !defined(WIN32) && (__STDC_VERSION__ < 199901L)
   #undef static
   #undef inline
diff --git a/ldecod/inc/macroblock.h b/ldecod/inc/macroblock.h
index 10951f0..2dc8cd2 100644
--- a/ldecod/inc/macroblock.h
+++ b/ldecod/inc/macroblock.h
@@ -16,307 +16,14 @@
 #define _MACROBLOCK_H_
 
 
-//! single scan pattern
-const byte SNGL_SCAN[16][2] =
-{
-  {0,0},{1,0},{0,1},{0,2},
-  {1,1},{2,0},{3,0},{2,1},
-  {1,2},{0,3},{1,3},{2,2},
-  {3,1},{3,2},{2,3},{3,3}
-};
-
-//! field scan pattern
-const byte FIELD_SCAN[16][2] =
-{
-  {0,0},{0,1},{1,0},{0,2},
-  {0,3},{1,1},{1,2},{1,3},
-  {2,0},{2,1},{2,2},{2,3},
-  {3,0},{3,1},{3,2},{3,3}
-};
-
-
-//! gives CBP value from codeword number, both for intra and inter
-const unsigned char NCBP[2][48][2]=
-{
-  {  // 0      1        2       3       4       5       6       7       8       9      10      11
-    {15, 0},{ 0, 1},{ 7, 2},{11, 4},{13, 8},{14, 3},{ 3, 5},{ 5,10},{10,12},{12,15},{ 1, 7},{ 2,11},
-    { 4,13},{ 8,14},{ 6, 6},{ 9, 9},{ 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}
-  },
-  {
-    {47, 0},{31,16},{15, 1},{ 0, 2},{23, 4},{27, 8},{29,32},{30, 3},{ 7, 5},{11,10},{13,12},{14,15},
-    {39,47},{43, 7},{45,11},{46,13},{16,14},{ 3, 6},{ 5, 9},{10,31},{12,35},{19,37},{21,42},{26,44},
-    {28,33},{35,34},{37,36},{42,40},{44,39},{ 1,43},{ 2,45},{ 4,46},{ 8,17},{17,18},{18,20},{20,24},
-    {24,19},{ 6,21},{ 9,26},{22,28},{25,23},{32,27},{33,29},{34,30},{36,22},{40,25},{38,38},{41,41}
-  }
-};
-
-
-//! used to control block sizes : Not used/16x16/16x8/8x16/8x8/8x4/4x8/4x4
-const int BLOCK_STEP[8][2]=
-{
-  {0,0},{4,4},{4,2},{2,4},{2,2},{2,1},{1,2},{1,1}
-};
-
-//! Dequantization coefficients
-const int dequant_coef[6][4][4] = {
-  {{10, 13, 10, 13},{ 13, 16, 13, 16},{10, 13, 10, 13},{ 13, 16, 13, 16}},
-  {{11, 14, 11, 14},{ 14, 18, 14, 18},{11, 14, 11, 14},{ 14, 18, 14, 18}},
-  {{13, 16, 13, 16},{ 16, 20, 16, 20},{13, 16, 13, 16},{ 16, 20, 16, 20}},
-  {{14, 18, 14, 18},{ 18, 23, 18, 23},{14, 18, 14, 18},{ 18, 23, 18, 23}},
-  {{16, 20, 16, 20},{ 20, 25, 20, 25},{16, 20, 16, 20},{ 20, 25, 20, 25}},
-  {{18, 23, 18, 23},{ 23, 29, 23, 29},{18, 23, 18, 23},{ 23, 29, 23, 29}}
-};
-
-const byte QP_SCALE_CR[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
-
-};
-
-//! single scan pattern
-const byte SNGL_SCAN8x8[64][2] = {
-  {0,0}, {1,0}, {0,1}, {0,2}, {1,1}, {2,0}, {3,0}, {2,1}, {1,2}, {0,3}, {0,4}, {1,3}, {2,2}, {3,1}, {4,0}, {5,0},
-  {4,1}, {3,2}, {2,3}, {1,4}, {0,5}, {0,6}, {1,5}, {2,4}, {3,3}, {4,2}, {5,1}, {6,0}, {7,0}, {6,1}, {5,2}, {4,3},
-  {3,4}, {2,5}, {1,6}, {0,7}, {1,7}, {2,6}, {3,5}, {4,4}, {5,3}, {6,2}, {7,1}, {7,2}, {6,3}, {5,4}, {4,5}, {3,6},
-  {2,7}, {3,7}, {4,6}, {5,5}, {6,4}, {7,3}, {7,4}, {6,5}, {5,6}, {4,7}, {5,7}, {6,6}, {7,5}, {7,6}, {6,7}, {7,7}
-};
-
-
-//! field scan pattern
-const byte FIELD_SCAN8x8[64][2] = {   // 8x8
-  {0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {0,3}, {0,4}, {1,2}, {2,0}, {1,3}, {0,5}, {0,6}, {0,7}, {1,4}, {2,1}, {3,0},
-  {2,2}, {1,5}, {1,6}, {1,7}, {2,3}, {3,1}, {4,0}, {3,2}, {2,4}, {2,5}, {2,6}, {2,7}, {3,3}, {4,1}, {5,0}, {4,2},
-  {3,4}, {3,5}, {3,6}, {3,7}, {4,3}, {5,1}, {6,0}, {5,2}, {4,4}, {4,5}, {4,6}, {4,7}, {5,3}, {6,1}, {6,2}, {5,4},
-  {5,5}, {5,6}, {5,7}, {6,3}, {7,0}, {7,1}, {6,4}, {6,5}, {6,6}, {6,7}, {7,2}, {7,3}, {7,4}, {7,5}, {7,6}, {7,7}
-};
-
-
-static const int dequant_coef8[6][8][8] =
-{
-  {
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18}
-  },
-  {
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19}
-  },
-  {
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23}
-  },
-  {
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25}
-  },
-  {
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28}
-  },
-  {
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32}
-  }
-
-};
-
-//! single scan pattern
-const byte SCAN_YUV422[8][2] =
-{
-  {0,0},{0,1},
-  {1,0},{0,2},
-  {0,3},{1,1},
-  {1,2},{1,3}
-};
+extern const byte QP_SCALE_CR[52];
 
 //! look up tables for FRExt_chroma support
-const unsigned char subblk_offset_x[3][8][4] =
-{
-  { {0, 4, 0, 4},
-    {0, 4, 0, 4},
-    {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, 4, 0, 4},
-    {0, 4, 0, 4},
-    {0, 4, 0, 4},
-    {0, 4, 0, 4},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0}, },
-
-  { {0, 4, 0, 4},
-    {8,12, 8,12},
-    {0, 4, 0, 4},
-    {8,12, 8,12},
-    {0, 4, 0, 4},
-    {8,12, 8,12},
-    {0, 4, 0, 4},
-    {8,12, 8,12}  }
-};
-
-const unsigned char subblk_offset_y[3][8][4] =
-{ { {0, 0, 4, 4},
-    {0, 0, 4, 4},
-    {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, 4, 4},
-    {8, 8,12,12},
-    {0, 0, 4, 4},
-    {8, 8,12,12},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0}  },
-
-  { {0, 0, 4, 4},
-    {0, 0, 4, 4},
-    {8, 8,12,12},
-    {8, 8,12,12},
-    {0, 0, 4, 4},
-    {0, 0, 4, 4},
-    {8, 8,12,12},
-    {8, 8,12,12} }
-};
-
-
-const unsigned char cofuv_blk_x[3][8][4] =
-{ { {0, 1, 0, 1},
-    {0, 1, 0, 1},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0} },
-
-  { {0, 1, 0, 1},
-    {0, 1, 0, 1},
-    {0, 1, 0, 1},
-    {0, 1, 0, 1},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0} },
-
-  { {0, 1, 0, 1},
-    {2, 3, 2, 3},
-    {0, 1, 0, 1},
-    {2, 3, 2, 3},
-    {0, 1, 0, 1},
-    {2, 3, 2, 3},
-    {0, 1, 0, 1},
-    {2, 3, 2, 3} }
-};
-  
-const unsigned char cofuv_blk_y[3][8][4] =
-{
-  { { 0, 0, 1, 1},
-    { 0, 0, 1, 1},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0} },
-
-  { { 0, 0, 1, 1},
-    { 2, 2, 3, 3},
-    { 0, 0, 1, 1},
-    { 2, 2, 3, 3},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0},
-    { 0, 0, 0, 0} },
-
-  { { 0, 0, 1, 1},
-    { 0, 0, 1, 1},
-    { 2, 2, 3, 3},
-    { 2, 2, 3, 3},
-    { 0, 0, 1, 1},
-    { 0, 0, 1, 1},
-    { 2, 2, 3, 3},
-    { 2, 2, 3, 3}}
-};
-
-static unsigned char cbp_blk_chroma[8][4] =
-{ {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} };
-
-
-int   block8x8_idx[3][4][4] =
-{ { {0, 1, 2, 3},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0}, },
-
-  { {0, 1, 0, 1},
-    {2, 3, 2, 3},
-    {0, 0, 0, 0},
-    {0, 0, 0, 0}  },
+extern const unsigned char subblk_offset_x[3][8][4];
+extern const unsigned char subblk_offset_y[3][8][4];
 
-  { {0, 0, 0, 0},
-    {1, 1, 1, 1},
-    {2, 2, 2, 2},
-    {3, 3, 3, 3}  }
-};
+extern void set_interpret_mb_mode(int slice_type);
+extern int  decode_one_macroblock(ImageParameters *img, Macroblock *currMB, StorablePicture *dec_picture);
 
 #endif
 
diff --git a/ldecod/inc/mbuffer.h b/ldecod/inc/mbuffer.h
index 84d4e2e..d608735 100644
--- a/ldecod/inc/mbuffer.h
+++ b/ldecod/inc/mbuffer.h
@@ -10,6 +10,8 @@
  *  \author
  *      Main contributors (see contributors.h for copyright, address and affiliation details)
  *      - Karsten Sühring          <suehring@hhi.de>
+ *      - Alexis Michael Tourapis  <alexismt@ieee.org>
+ 
  *      - Jill Boyce               <jill.boyce@thomson.net>
  *      - Saurav K Bandyopadhyay   <saurav@ieee.org>
  *      - Zhenyu Wu                <Zhenyu.Wu@thomson.net
@@ -23,6 +25,16 @@
 #include "global.h"
 
 #define MAX_LIST_SIZE 33
+//! definition of pic motion parameters
+typedef struct pic_motion_params
+{
+  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
+  int64 ***   ref_id;        //!< reference picture identifier [list][subblock_y][subblock_x]
+  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
+  byte *      mb_field;      //!< field macroblock indicator
+  byte **     field_frame;   //!< indicates if co_located is field or frame.
+} PicMotionParams;
 
 //! definition a picture (field or frame)
 typedef struct storable_picture
@@ -61,25 +73,11 @@ typedef struct storable_picture
 
   imgpel **     imgY;         //!< Y picture component
   imgpel ***    imgUV;        //!< U and V picture components
+  
+  PicMotionParams motion;              //!< Motion info
+  PicMotionParams JVmotion[MAX_PLANE]; //!< Motion info for 4:4:4 independent mode decoding
 
-  byte  *      mb_field;      //!< field macroblock indicator
   short **     slice_id;      //!< reference picture   [mb_x][mb_y]
-  char  ***    ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-
-  int64 ***    ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-                              //   (not  simply index)
-  int64 ***    ref_id;        //!< reference picture identifier [list][subblock_y][subblock_x]
-                              //   (not  simply index)
-
-  short ****   mv;            //!< motion vector       [list][subblock_y][subblock_x][component]
-
-  char  ***   ref_idx_JV[MAX_PLANE];       //!< ref_idx to be used for 4:4:4 independent mode decoding
-  int64 ***   ref_pic_id_JV[MAX_PLANE];    //!< ref_pic_id to be used for 4:4:4 independent mode decoding
-  int64 ***   ref_id_JV[MAX_PLANE];        //!< ref_id to be used for 4:4:4 independent mode decoding
-  short ****  mv_JV[MAX_PLANE];            //!< mv to be used for 4:4:4 independent mode decoding
-
-  byte **     moving_block;
-  byte **     field_frame;         //!< indicates if co_located is field or frame.
 
   struct storable_picture *top_field;     // for mb aff, if frame for referencing the top field
   struct storable_picture *bottom_field;  // for mb aff, if frame for referencing the bottom field
@@ -113,36 +111,25 @@ typedef struct storable_picture
   imgpel*     tone_mapping_lut;                //!< tone mapping look up table
 } StorablePicture;
 
+//! definition of motion parameters
+typedef struct motion_params
+{
+  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
+  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
+  byte **     moving_block;
+} MotionParams;
 
 //! definition a picture (field or frame)
 typedef struct colocated_params
 {
   int         mb_adaptive_frame_field_flag;
   int         size_x, size_y;
-
-  int64       ref_pic_num[6][MAX_LIST_SIZE];
-
-  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  mv;            //!< motion vector       [list][subblock_y][subblock_x][component]
-  byte  **    moving_block;
-
-  // Top field params
-  int64       top_ref_pic_num[6][MAX_LIST_SIZE];
-  char  ***   top_ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   top_ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  top_mv;            //!< motion vector       [list][subblock_y][subblock_x][component]
-  byte **     top_moving_block;
-
-  // Bottom field params
-  int64       bottom_ref_pic_num[6][MAX_LIST_SIZE];
-  char  ***   bottom_ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   bottom_ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  bottom_mv;            //!< motion vector       [list][subblock_y][subblock_x][component]
-  byte **     bottom_moving_block;
-
   byte        is_long_term;
-  byte **     field_frame;         //!< indicates if co_located is field or frame.
+
+  MotionParams frame;
+  MotionParams top;
+  MotionParams bottom;
 
 } ColocatedParams;
 
@@ -228,7 +215,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6]);
 
 // For 4:4:4 independent mode
 void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6]);
-void copy_storable_param_JV( int nplane, StorablePicture *d, StorablePicture *s );
+void copy_storable_param_JV( PicMotionParams  *JVplane, PicMotionParams  *motion );
 
 #endif
 
diff --git a/ldecod/inc/memalloc.h b/ldecod/inc/memalloc.h
index a298348..18735d7 100644
--- a/ldecod/inc/memalloc.h
+++ b/ldecod/inc/memalloc.h
@@ -8,6 +8,9 @@
  *
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Karsten Sühring                 <suehring@hhi.de> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
+ *
  ************************************************************************
  */
 
@@ -23,32 +26,37 @@ int  get_mem2Dint(int ***array2D, int rows, int columns);
 int  get_mem3Dint(int ****array3D, int frames, int rows, int columns);
 int  get_mem4Dint(int *****array4D, int idx, int frames, int rows, int columns );
 
-int  get_mem3Dint64(int64 ****array3D, int frames, int rows, int columns);
+
 int  get_mem2Dint64(int64 ***array2D, int rows, int columns);
+int  get_mem3Dint64(int64 ****array3D, int frames, int rows, int columns);
+
+int  get_mem2Dshort(short ***array2D, int dim0, int dim1);
+int  get_mem3Dshort(short ****array3D, int dim0, int dim1, int dim2);
+int  get_mem4Dshort(short *****array4D, int dim0, int dim1, int dim2, int dim3);
+
+
+int  get_mem2Dpel(imgpel ***array2D, int rows, int columns);
+int  get_mem3Dpel(imgpel ****array3D, int frames, int rows, int columns);
+
 
-int  get_mem2Dshort(short ***array2D, int rows, int columns);
-int  get_mem3Dshort(short ****array3D, int frames, int rows, int columns);
-int  get_mem4Dshort(short *****array4D, int idx, int frames, int rows, int columns );
+void free_mem2D     (byte      **array2D);
+void free_mem3D     (byte     ***array2D);
 
-int get_mem2Dpel(imgpel  ***array2D, int rows, int columns);
-int get_mem3Dpel(imgpel ****array3D, int frames, int rows, int columns);
 
-void free_mem2D(byte **array2D);
-void free_mem3D(byte ***array2D);
+void free_mem2Dint  (int       **array2D);
+void free_mem3Dint  (int      ***array3D);
+void free_mem4Dint  (int     ****array4D);
 
-void free_mem2Dint(int   **array2D);
-void free_mem3Dint(int  ***array3D);
-void free_mem4Dint(int ****array4D);
 
-void free_mem2Dint64(int64  **array2D);
-void free_mem3Dint64(int64 ***array3D);
+void free_mem2Dint64(int64     **array2D);
+void free_mem3Dint64(int64    ***array3D);
 
-void free_mem2Dshort(short  **array2D);
-void free_mem3Dshort(short  ***array3D);
-void free_mem4Dshort(short ****array4D);
+void free_mem2Dshort(short      **array2D);
+void free_mem3Dshort(short     ***array3D);
+void free_mem4Dshort(short    ****array4D);
 
-void free_mem2Dpel(imgpel  **array2D);
-void free_mem3Dpel(imgpel ***array3D);
+void free_mem2Dpel  (imgpel    **array2D);
+void free_mem3Dpel  (imgpel   ***array3D);
 
 void no_mem_exit(char *where);
 
diff --git a/ldecod/inc/nalu.h b/ldecod/inc/nalu.h
index d7fc689..51f46c8 100644
--- a/ldecod/inc/nalu.h
+++ b/ldecod/inc/nalu.h
@@ -21,7 +21,8 @@
 
 extern FILE *bits;
 
-int GetAnnexbNALU (NALU_t *nalu);
+//int GetAnnexbNALU (NALU_t *nalu);
+int read_next_nalu(FILE *bitstream, NALU_t *nalu);
 int NALUtoRBSP (NALU_t *nalu);
 
 #endif
diff --git a/ldecod/inc/quant.h b/ldecod/inc/quant.h
new file mode 100644
index 0000000..bb6608a
--- /dev/null
+++ b/ldecod/inc/quant.h
@@ -0,0 +1,50 @@
+
+/*!
+ ************************************************************************
+ * \file quant.h
+ *
+ * \brief
+ *    definitions for quantization functions
+ *
+ * \author
+ *
+ ************************************************************************
+ */
+
+#ifndef _QUANT_H_
+#define _QUANT_H_
+
+// Macro defines
+#define Q_BITS          15
+#define DQ_BITS          6
+#define Q_BITS_8        16
+#define DQ_BITS_8        6 
+
+// exported variables
+extern const int dequant_coef[6][4][4];
+extern const int quant_coef[6][4][4];
+
+extern int InvLevelScale4x4_Intra[3][6][4][4];
+extern int InvLevelScale4x4_Inter[3][6][4][4];
+extern int InvLevelScale8x8_Intra[3][6][8][8];
+extern int InvLevelScale8x8_Inter[3][6][8][8];
+
+extern int *qmatrix[12];
+
+// SP decoding parameter (EQ. 8-425)
+extern const int A[4][4];
+
+extern int *qp_per_matrix;
+extern int *qp_rem_matrix;
+
+// exported functions
+// quantization initialization
+void init_qp_process(ImageParameters *img);
+
+// For Q-matrix
+void AssignQuantParam(pic_parameter_set_rbsp_t* pps, seq_parameter_set_rbsp_t* sps);
+void CalculateQuantParam(void);
+void CalculateQuant8Param(void);
+
+#endif
+
diff --git a/ldecod/inc/rtp.h b/ldecod/inc/rtp.h
index 7fd806b..143e529 100644
--- a/ldecod/inc/rtp.h
+++ b/ldecod/inc/rtp.h
@@ -40,7 +40,7 @@ typedef struct
 
 void DumpRTPHeader (RTPpacket_t *p);
 
-int  GetRTPNALU (NALU_t *nalu);
+int  GetRTPNALU (FILE *bitstream, NALU_t *nalu);
 void OpenRTPFile (char *fn);
 void CloseRTPFile(void);
 
diff --git a/ldecod/inc/transform8x8.h b/ldecod/inc/transform8x8.h
index 8b8ade1..9851f09 100644
--- a/ldecod/inc/transform8x8.h
+++ b/ldecod/inc/transform8x8.h
@@ -17,7 +17,6 @@
 #ifndef _TRANSFORM8X8_H_
 #define _TRANSFORM8X8_H_
 
-int    intrapred8x8(ColorPlane pl, ImageParameters *img, Macroblock *currMB, int b8);
-void   itrans8x8(ColorPlane pl, ImageParameters *img, int ioff, int joff);
+int    intrapred8x8(ImageParameters *img, Macroblock *currMB, ColorPlane pl, int b8);
 
 #endif
diff --git a/ldecod/src/annexb.c b/ldecod/src/annexb.c
index 9cd9026..e0481d3 100644
--- a/ldecod/src/annexb.c
+++ b/ldecod/src/annexb.c
@@ -44,7 +44,7 @@ int NALUCount=0;
  ************************************************************************
  */
 
-int GetAnnexbNALU (NALU_t *nalu)
+int GetAnnexbNALU (FILE *bitstream, NALU_t *nalu)
 {
   int info2, info3, pos = 0;
   int StartCodeFound, rewind;
@@ -53,9 +53,9 @@ int GetAnnexbNALU (NALU_t *nalu)
 
   if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL) no_mem_exit("GetAnnexbNALU: Buf");
 
-  while(!feof(bits) && (Buf[pos++]= (unsigned char) fgetc(bits))==0);
+  while(!feof(bitstream) && (Buf[pos++]= (unsigned char) fgetc(bitstream))==0);
 
-  if(feof(bits))
+  if(feof(bitstream))
   {
     if(pos==0)
     {
@@ -111,7 +111,7 @@ int GetAnnexbNALU (NALU_t *nalu)
 
   while (!StartCodeFound)
   {
-    if (feof (bits))
+    if (feof (bitstream))
     {
       //Count the trailing_zero_8bits
       while(Buf[pos-2-TrailingZero8Bits]==0)
@@ -133,7 +133,7 @@ int GetAnnexbNALU (NALU_t *nalu)
       free(Buf);
       return pos-1;
     }
-    Buf[pos++] = (unsigned char) fgetc (bits);
+    Buf[pos++] = (unsigned char) fgetc (bitstream);
     info3 = FindStartCode(&Buf[pos-4], 3);
     if(info3 != 1)
       info2 = FindStartCode(&Buf[pos-3], 2);
@@ -160,7 +160,7 @@ int GetAnnexbNALU (NALU_t *nalu)
     return -1;
   }
 
-  if (0 != fseek (bits, rewind, SEEK_CUR))
+  if (0 != fseek (bitstream, rewind, SEEK_CUR))
   {
     snprintf (errortext, ET_SIZE, "GetAnnexbNALU: Cannot fseek %d in the bit stream file", rewind);
     free(Buf);
diff --git a/ldecod/src/block.c b/ldecod/src/block.c
index 4e94077..575d1ec 100644
--- a/ldecod/src/block.c
+++ b/ldecod/src/block.c
@@ -21,80 +21,7 @@
 #include "image.h"
 #include "mb_access.h"
 #include "transform.h"
-
-#define Q_BITS          15
-
-extern const unsigned char cofuv_blk_y[3][8][4];
-extern const unsigned char cofuv_blk_x[3][8][4];
-
-static const int quant_coef[6][4][4] = {
-  {{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243},{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243}},
-  {{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660},{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660}},
-  {{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194},{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194}},
-  {{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647},{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647}},
-  {{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355},{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355}},
-  {{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893},{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893}}
-};
-static const int A[4][4] = {
-  { 16, 20, 16, 20},
-  { 20, 25, 20, 25},
-  { 16, 20, 16, 20},
-  { 20, 25, 20, 25}
-};
-
-int quant_intra_default[16] = {
- 6,13,20,28,
-13,20,28,32,
-20,28,32,37,
-28,32,37,42
-};
-
-int quant_inter_default[16] = {
-10,14,20,24,
-14,20,24,27,
-20,24,27,30,
-24,27,30,34
-};
-
-int quant8_intra_default[64] = {
- 6,10,13,16,18,23,25,27,
-10,11,16,18,23,25,27,29,
-13,16,18,23,25,27,29,31,
-16,18,23,25,27,29,31,33,
-18,23,25,27,29,31,33,36,
-23,25,27,29,31,33,36,38,
-25,27,29,31,33,36,38,40,
-27,29,31,33,36,38,40,42
-};
-
-int quant8_inter_default[64] = {
- 9,13,15,17,19,21,22,24,
-13,13,17,19,21,22,24,25,
-15,17,19,21,22,24,25,27,
-17,19,21,22,24,25,27,28,
-19,21,22,24,25,27,28,30,
-21,22,24,25,27,28,30,32,
-22,24,25,27,28,30,32,33,
-24,25,27,28,30,32,33,35
-};
-
-int quant_org[16] = { //to be use if no q matrix is chosen
-16,16,16,16,
-16,16,16,16,
-16,16,16,16,
-16,16,16,16
-};
-
-int quant8_org[64] = { //to be use if no q matrix is chosen
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16
-};
+#include "quant.h"
 
 // Notation for comments regarding prediction and predictors.
 // The pels of the 4x4 block are labelled a..p. The predictor pels above
@@ -122,7 +49,9 @@ int quant8_org[64] = { //to be use if no q matrix is chosen
 #define P_K (PredPel[11])
 #define P_L (PredPel[12])
 
-  static int M4[4][4];
+  static int M4[BLOCK_SIZE][BLOCK_SIZE];
+  static int PBlock[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
+
 static void intra_chroma_DC_single(imgpel **curr_img, int up_avail, int left_avail, PixelPos up, PixelPos left[17], int blk_x, int blk_y, int *pred, int direction )
 {
   static int i;
@@ -174,13 +103,13 @@ static void intra_chroma_DC_all(imgpel **curr_img, int up_avail, int left_avail,
  *    SEARCH_SYNC   search next sync element as errors while decoding occured
  ***********************************************************************
  */
-int intrapred( Macroblock *currMB, 
-               ColorPlane pl,
-               ImageParameters *img,  //!< image parameters
-               int ioff,             //!< pixel offset X within MB
-               int joff,             //!< pixel offset Y within MB
-               int img_block_x,      //!< location of block X, multiples of 4
-               int img_block_y)      //!< location of block Y, multiples of 4
+int intrapred(ImageParameters *img,  //!< image parameters 
+              Macroblock *currMB, 
+              ColorPlane pl,               
+              int ioff,             //!< pixel offset X within MB
+              int joff,             //!< pixel offset Y within MB
+              int img_block_x,      //!< location of block X, multiples of 4
+              int img_block_y)      //!< location of block Y, multiples of 4
 {
   int i,j;
   int s0;  
@@ -199,7 +128,7 @@ int intrapred( Macroblock *currMB,
   byte predmode = img->ipredmode[img_block_y][img_block_x];
   int jpos0 = joff, jpos1 = joff + 1, jpos2 = joff + 2, jpos3 = joff + 3;
   int ipos0 = ioff, ipos1 = ioff + 1, ipos2 = ioff + 2, ipos3 = ioff + 3;
-  imgpel *predrow, prediction, (*mpr)[16] = img->mpr[pl];
+  imgpel *predrow, prediction, (*mpr)[16] = img->mb_pred[pl];
 
   ipmode_DPCM = predmode; //For residual DPCM
 
@@ -483,9 +412,9 @@ int intrapred( Macroblock *currMB,
  *    best SAD
  ***********************************************************************
  */ 
-int intrapred_luma_16x16(Macroblock *currMB,  //!< Current Macroblock
-                         ColorPlane pl,       //!< Current colorplane (for 4:4:4)
-                         ImageParameters *img, //!< image parameters
+int intrapred_luma_16x16(ImageParameters *img, //!< image parameters
+                         Macroblock *currMB,  //!< Current Macroblock
+                         ColorPlane pl,       //!< Current colorplane (for 4:4:4)                         
                          int predmode)        //!< prediction mode
 {
   int s0 = 0, s1, s2;
@@ -497,9 +426,10 @@ int intrapred_luma_16x16(Macroblock *currMB,  //!< Current Macroblock
 
   int uv = pl-1;
   imgpel **imgY = (pl) ? dec_picture->imgUV[uv] : dec_picture->imgY;
-  imgpel (*mpr)[MB_BLOCK_SIZE] = &(img->mpr[pl][0]); 
+  imgpel (*mpr)[MB_BLOCK_SIZE] = &(img->mb_pred[pl][0]); 
   imgpel *mpr_line;
   imgpel prediction;
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
 
   PixelPos up;          //!< pixel position p(0,-1)
   PixelPos left[17];    //!< pixel positions p(-1, -1..15)
@@ -534,7 +464,7 @@ int intrapred_luma_16x16(Macroblock *currMB,  //!< Current Macroblock
     if (!up_avail)
       error ("invalid 16x16 intra pred Mode VERT_PRED_16",500);
     for(j=0;j<MB_BLOCK_SIZE;j++)
-      memcpy(img->mpr[pl][j], &(imgY[up.pos_y][up.pos_x]), MB_BLOCK_SIZE * sizeof(imgpel));
+      memcpy(img->mb_pred[pl][j], &(imgY[up.pos_y][up.pos_x]), MB_BLOCK_SIZE * sizeof(imgpel));
     break;
   case HOR_PRED_16:                        // horizontal prediction from left block
     if (!left_avail)
@@ -596,7 +526,7 @@ int intrapred_luma_16x16(Macroblock *currMB,  //!< Current Macroblock
     {
       for (i=0;i< MB_BLOCK_SIZE;i++)
       {
-        mpr[j][i]=(imgpel) iClip1(img->max_imgpel_value_comp[pl],((iaa+(i-7)*ib +(j-7)*ic + 16)>>5));
+        mpr[j][i]=(imgpel) iClip1(max_imgpel_value,((iaa+(i-7)*ib +(j-7)*ic + 16)>>5));
       }
     }// store plane prediction
     break;
@@ -619,12 +549,13 @@ int intrapred_luma_16x16(Macroblock *currMB,  //!< Current Macroblock
  ************************************************************************
  */
 
-void intrapred_chroma(Macroblock *currMB, ImageParameters *img, int uv)
+void intrapred_chroma(ImageParameters *img, Macroblock *currMB, int uv)
 {
   int i,j, ii, jj;
 
   imgpel **imgUV = dec_picture->imgUV[uv];
-  imgpel (*mpr)[16] = img->mpr[uv + 1];
+  imgpel (*mpr)[16] = img->mb_pred[uv + 1];
+  int     max_imgpel_value = img->max_imgpel_value_comp[uv + 1];
   
   int ih, iv, ib, ic, iaa;
 
@@ -759,7 +690,7 @@ void intrapred_chroma(Macroblock *currMB, ImageParameters *img, int uv)
 
       for (j = 0; j < cr_MB_y; j++)
         for (i = 0; i < cr_MB_x; i++)
-          mpr[j][i]=(imgpel) iClip1(img->max_imgpel_value_uv,((iaa + (i - cr_MB_x2 + 1) * ib + (j - cr_MB_y2 + 1) * ic + 16) >> 5));  }
+          mpr[j][i]=(imgpel) iClip1(max_imgpel_value, ((iaa + (i - cr_MB_x2 + 1) * ib + (j - cr_MB_y2 + 1) * ic + 16) >> 5));  }
     break;
   default:
     error("illegal chroma intra prediction mode", 600);
@@ -773,26 +704,27 @@ void intrapred_chroma(Macroblock *currMB, ImageParameters *img, int uv)
  *    Inverse 4x4 transformation, transforms cof to m7
  ***********************************************************************
  */
-void itrans4x4(ColorPlane pl,  
-            ImageParameters *img, //!< image parameters
-            int ioff,            //!< index to 4x4 block
-            int joff)            //!<
+void itrans4x4(ImageParameters *img, //!< image parameters
+               ColorPlane pl,              
+               int ioff,            //!< index to 4x4 block
+               int joff)            //!<
 {
   static int i,j;
 
-  int max_imgpel_value = pl ? img->max_imgpel_value_uv : img->max_imgpel_value;
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
 
-  imgpel (*mpr)[16] = img->mpr[pl];
-  int (*m7)[16] = img->m7[pl];
+  imgpel (*mpr)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*m7) [MB_BLOCK_SIZE] = img->mb_rres[pl];
 
   inverse4x4(img->cof[pl],m7,joff,ioff);
 
   for (j = joff; j < joff + BLOCK_SIZE; j++)
+  {
     for (i = ioff; i < ioff + BLOCK_SIZE; i++)
     {      
       m7[j][i] = iClip1(max_imgpel_value, rshift_rnd_sf((m7[j][i] + ((long)mpr[j][i] << DQ_BITS)), DQ_BITS));
     }
-
+  }
 }
 
 /*!
@@ -801,17 +733,17 @@ void itrans4x4(ColorPlane pl,
  *    Inverse 4x4 lossless_qpprime transformation, transforms cof to m7
  ***********************************************************************
  */
-void itrans4x4_ls(ColorPlane pl,        //!< Color plane (for 4:4:4)
-                  ImageParameters *img, //!< image parameters
+void itrans4x4_ls(ImageParameters *img, //!< image parameters
+                  ColorPlane pl,        //!< Color plane (for 4:4:4)                  
                   int ioff,             //!< index to 4x4 block
                   int joff)             //!<
 {
   static int i,j;
 
-  int max_imgpel_value = pl ? img->max_imgpel_value_uv : img->max_imgpel_value;
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
 
-  imgpel (*mpr)[16] = img->mpr[pl];
-  int    ( *m7)[16] = img->m7 [pl];
+  imgpel (*mpr)[16] = img->mb_pred[pl];
+  int    ( *m7)[16] = img->mb_rres [pl];
 
   inverse4x4(img->cof[pl],m7,joff,ioff);
 
@@ -833,59 +765,60 @@ void itrans4x4_ls(ColorPlane pl,        //!< Color plane (for 4:4:4)
 *    ioff_x,joff_y: Block position inside a macro block (0,4,8,12).
 ************************************************************************
 */  //For residual DPCM
-void Inv_Residual_trans_4x4(ColorPlane pl, 
-                           ImageParameters *img, //!< image parameters
-                           int ioff,            //!< index to 4x4 block
-                           int joff)
+void Inv_Residual_trans_4x4(ImageParameters *img, //!< image parameters
+                            ColorPlane pl,                            
+                            int ioff,            //!< index to 4x4 block
+                            int joff)
 {
   int i,j;
   int temp[4][4];
-  imgpel (*mpr)[16] = img->mpr[pl];
-
+  imgpel (*mpr)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*m7) [MB_BLOCK_SIZE] = img->mb_rres[pl];
+  int    (*cof)[MB_BLOCK_SIZE] = img->cof[pl];
 
   if(ipmode_DPCM==VERT_PRED)
   {
     for(i=0; i<4; i++)
     {
-      temp[0][i] = img->cof[pl][joff + 0][ioff + i];
-      temp[1][i] = img->cof[pl][joff + 1][ioff + i] + temp[0][i];
-      temp[2][i] = img->cof[pl][joff + 2][ioff + i] + temp[1][i];
-      temp[3][i] = img->cof[pl][joff + 3][ioff + i] + temp[2][i];
+      temp[0][i] = cof[joff + 0][ioff + i];
+      temp[1][i] = cof[joff + 1][ioff + i] + temp[0][i];
+      temp[2][i] = cof[joff + 2][ioff + i] + temp[1][i];
+      temp[3][i] = cof[joff + 3][ioff + i] + temp[2][i];
     }
     for(i=0; i<4; i++)
     {
-      img->m7[pl][joff    ][ioff + i]=temp[0][i];
-      img->m7[pl][joff + 1][ioff + i]=temp[1][i];
-      img->m7[pl][joff + 2][ioff + i]=temp[2][i];
-      img->m7[pl][joff + 3][ioff + i]=temp[3][i];
+      m7[joff    ][ioff + i]=temp[0][i];
+      m7[joff + 1][ioff + i]=temp[1][i];
+      m7[joff + 2][ioff + i]=temp[2][i];
+      m7[joff + 3][ioff + i]=temp[3][i];
     }
   }
   else if(ipmode_DPCM==HOR_PRED)
   {
     for(j=0; j<4; j++)
     {
-      temp[j][0] = img->cof[pl][joff + j][ioff    ];
-      temp[j][1] = img->cof[pl][joff + j][ioff + 1] + temp[j][0];
-      temp[j][2] = img->cof[pl][joff + j][ioff + 2] + temp[j][1];
-      temp[j][3] = img->cof[pl][joff + j][ioff + 3] + temp[j][2];
+      temp[j][0] = cof[joff + j][ioff    ];
+      temp[j][1] = cof[joff + j][ioff + 1] + temp[j][0];
+      temp[j][2] = cof[joff + j][ioff + 2] + temp[j][1];
+      temp[j][3] = cof[joff + j][ioff + 3] + temp[j][2];
     }
     for(j=0; j<4; j++)
     {
-      img->m7[pl][joff + j][ioff    ]=temp[j][0];
-      img->m7[pl][joff + j][ioff + 1]=temp[j][1];
-      img->m7[pl][joff + j][ioff + 2]=temp[j][2];
-      img->m7[pl][joff + j][ioff + 3]=temp[j][3];
+      m7[joff + j][ioff    ]=temp[j][0];
+      m7[joff + j][ioff + 1]=temp[j][1];
+      m7[joff + j][ioff + 2]=temp[j][2];
+      m7[joff + j][ioff + 3]=temp[j][3];
     }
   }
   else
   {
     for (j = 0; j < BLOCK_SIZE; j++)
       for (i = 0; i < BLOCK_SIZE; i++)
-        img->m7[pl][joff+j][ioff+i] = img->cof[pl][joff+j][ioff+i];
+        m7[joff+j][ioff+i] = cof[joff+j][ioff+i];
   }
   for (j = 0; j < BLOCK_SIZE; j++)
     for (i = 0; i < BLOCK_SIZE; i++)
-      img->m7[pl][joff+j][ioff+i] =  img->m7[pl][joff+j][ioff+i] + (long)mpr[joff+j][ioff+i];
+      m7[joff+j][ioff+i] +=  (long)mpr[joff+j][ioff+i];
 
 }
 
@@ -899,225 +832,70 @@ void Inv_Residual_trans_4x4(ColorPlane pl,
 ************************************************************************
 */
 //For residual DPCM
-void Inv_Residual_trans_8x8(ColorPlane pl, ImageParameters *img, int ioff,int joff)
+void Inv_Residual_trans_8x8(ImageParameters *img, Macroblock *currMB, ColorPlane pl, int ioff,int joff)
 {
   int i, j;
   int temp[8][8];
-  imgpel (*mpr)[16] = img->mpr[pl];
+  imgpel (*mpr)[16] = img->mb_pred[pl];
+  int    (*m7) [16] = img->mb_rres[pl];
+  
 
   if(ipmode_DPCM==VERT_PRED)
     {
       for(i=0; i<8; i++)
       {
-        temp[0][i] = img->m7[pl][joff + 0][ioff + i];
-        temp[1][i] = img->m7[pl][joff + 1][ioff + i] + temp[0][i];
-        temp[2][i] = img->m7[pl][joff + 2][ioff + i] + temp[1][i];
-        temp[3][i] = img->m7[pl][joff + 3][ioff + i] + temp[2][i];
-        temp[4][i] = img->m7[pl][joff + 4][ioff + i] + temp[3][i];
-        temp[5][i] = img->m7[pl][joff + 5][ioff + i] + temp[4][i];
-        temp[6][i] = img->m7[pl][joff + 6][ioff + i] + temp[5][i];
-        temp[7][i] = img->m7[pl][joff + 7][ioff + i] + temp[6][i];
+        temp[0][i] = m7[joff + 0][ioff + i];
+        temp[1][i] = m7[joff + 1][ioff + i] + temp[0][i];
+        temp[2][i] = m7[joff + 2][ioff + i] + temp[1][i];
+        temp[3][i] = m7[joff + 3][ioff + i] + temp[2][i];
+        temp[4][i] = m7[joff + 4][ioff + i] + temp[3][i];
+        temp[5][i] = m7[joff + 5][ioff + i] + temp[4][i];
+        temp[6][i] = m7[joff + 6][ioff + i] + temp[5][i];
+        temp[7][i] = m7[joff + 7][ioff + i] + temp[6][i];
       }
       for(i=0; i<8; i++)
       {
-        img->m7[pl][joff  ][ioff+i]=temp[0][i];
-        img->m7[pl][joff+1][ioff+i]=temp[1][i];
-        img->m7[pl][joff+2][ioff+i]=temp[2][i];
-        img->m7[pl][joff+3][ioff+i]=temp[3][i];
-        img->m7[pl][joff+4][ioff+i]=temp[4][i];
-        img->m7[pl][joff+5][ioff+i]=temp[5][i];
-        img->m7[pl][joff+6][ioff+i]=temp[6][i];
-        img->m7[pl][joff+7][ioff+i]=temp[7][i];
+        m7[joff  ][ioff+i]=temp[0][i];
+        m7[joff+1][ioff+i]=temp[1][i];
+        m7[joff+2][ioff+i]=temp[2][i];
+        m7[joff+3][ioff+i]=temp[3][i];
+        m7[joff+4][ioff+i]=temp[4][i];
+        m7[joff+5][ioff+i]=temp[5][i];
+        m7[joff+6][ioff+i]=temp[6][i];
+        m7[joff+7][ioff+i]=temp[7][i];
       }
     }
     else if(ipmode_DPCM==HOR_PRED)//HOR_PRED
     {
       for(i=0; i<8; i++)
       {
-        temp[i][0] = img->m7[pl][joff + i][ioff + 0];
-        temp[i][1] = img->m7[pl][joff + i][ioff + 1] + temp[i][0];
-        temp[i][2] = img->m7[pl][joff + i][ioff + 2] + temp[i][1];
-        temp[i][3] = img->m7[pl][joff + i][ioff + 3] + temp[i][2];
-        temp[i][4] = img->m7[pl][joff + i][ioff + 4] + temp[i][3];
-        temp[i][5] = img->m7[pl][joff + i][ioff + 5] + temp[i][4];
-        temp[i][6] = img->m7[pl][joff + i][ioff + 6] + temp[i][5];
-        temp[i][7] = img->m7[pl][joff + i][ioff + 7] + temp[i][6];
+        temp[i][0] = m7[joff + i][ioff + 0];
+        temp[i][1] = m7[joff + i][ioff + 1] + temp[i][0];
+        temp[i][2] = m7[joff + i][ioff + 2] + temp[i][1];
+        temp[i][3] = m7[joff + i][ioff + 3] + temp[i][2];
+        temp[i][4] = m7[joff + i][ioff + 4] + temp[i][3];
+        temp[i][5] = m7[joff + i][ioff + 5] + temp[i][4];
+        temp[i][6] = m7[joff + i][ioff + 6] + temp[i][5];
+        temp[i][7] = m7[joff + i][ioff + 7] + temp[i][6];
       }
       for(i=0; i<8; i++)
       {
-        img->m7[pl][joff+i][ioff+0]=temp[i][0];
-        img->m7[pl][joff+i][ioff+1]=temp[i][1];
-        img->m7[pl][joff+i][ioff+2]=temp[i][2];
-        img->m7[pl][joff+i][ioff+3]=temp[i][3];
-        img->m7[pl][joff+i][ioff+4]=temp[i][4];
-        img->m7[pl][joff+i][ioff+5]=temp[i][5];
-        img->m7[pl][joff+i][ioff+6]=temp[i][6];
-        img->m7[pl][joff+i][ioff+7]=temp[i][7];
+        m7[joff+i][ioff+0]=temp[i][0];
+        m7[joff+i][ioff+1]=temp[i][1];
+        m7[joff+i][ioff+2]=temp[i][2];
+        m7[joff+i][ioff+3]=temp[i][3];
+        m7[joff+i][ioff+4]=temp[i][4];
+        m7[joff+i][ioff+5]=temp[i][5];
+        m7[joff+i][ioff+6]=temp[i][6];
+        m7[joff+i][ioff+7]=temp[i][7];
       }
     }
     for (j = 0; j < BLOCK_SIZE*2; j++)
       for (i = 0; i < BLOCK_SIZE*2; i++)
-        img->m7[pl][j+joff][i+ioff] =  img->m7[pl][j+joff][i+ioff] + (long)mpr[j+joff][i+ioff];
+        m7[j+joff][i+ioff] +=  (long)mpr[j+joff][i+ioff];
 }
 
-/*!
- ************************************************************************
- * \brief
- *    For mapping the q-matrix to the active id and calculate quantisation values
- *
- * \param pps
- *    Picture parameter set
- * \param sps
- *    Sequence parameter set
- *
- ************************************************************************
- */
-void AssignQuantParam(pic_parameter_set_rbsp_t* pps, seq_parameter_set_rbsp_t* sps)
-{
-  int i;
-  int n_ScalingList;
 
-  if(!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag)
-  {
-    for(i=0; i<12; i++)
-      qmatrix[i] = (i<6) ? quant_org:quant8_org;
-  }
-  else
-  {
-    n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;
-    if(sps->seq_scaling_matrix_present_flag) // check sps first
-    {
-      for(i=0; i<n_ScalingList; i++)
-      {
-        if(i<6)
-        {
-          if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A
-          {
-            if(i==0)
-              qmatrix[i] = quant_intra_default;
-            else if(i==3)
-              qmatrix[i] = quant_inter_default;
-            else
-              qmatrix[i] = qmatrix[i-1];
-          }
-          else
-          {
-            if(sps->UseDefaultScalingMatrix4x4Flag[i])
-              qmatrix[i] = (i<3) ? quant_intra_default : quant_inter_default;
-            else
-              qmatrix[i] = sps->ScalingList4x4[i];
-          }
-        }
-        else
-        {
-          if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A
-          {
-            if(i==6)
-              qmatrix[i] = quant8_intra_default;
-            else if(i==7)
-              qmatrix[i] = quant8_inter_default;
-            else
-              qmatrix[i] = qmatrix[i-2];
-          }
-          else
-          {
-            if(sps->UseDefaultScalingMatrix8x8Flag[i-6])
-              qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;
-            else
-              qmatrix[i] = sps->ScalingList8x8[i-6];
-          }
-        }
-      }
-    }
-
-    if(pps->pic_scaling_matrix_present_flag) // then check pps
-    {
-      for(i=0; i<n_ScalingList; i++)
-      {
-        if(i<6)
-        {
-          if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B
-          {
-            if (i==0)
-            {
-              if(!sps->seq_scaling_matrix_present_flag)
-                qmatrix[i] = quant_intra_default;
-            }
-            else if (i==3)
-            {
-              if(!sps->seq_scaling_matrix_present_flag)
-                qmatrix[i] = quant_inter_default;
-            }
-            else
-              qmatrix[i] = qmatrix[i-1];
-          }
-          else
-          {
-            if(pps->UseDefaultScalingMatrix4x4Flag[i])
-              qmatrix[i] = (i<3) ? quant_intra_default:quant_inter_default;
-            else
-              qmatrix[i] = pps->ScalingList4x4[i];
-          }
-        }
-        else
-        {
-          if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B
-          {
-            if (i==6)
-            {
-              if(!sps->seq_scaling_matrix_present_flag)
-                qmatrix[i] = quant8_intra_default;
-            }
-            else if(i==7)
-            {
-              if(!sps->seq_scaling_matrix_present_flag)
-                qmatrix[i] = quant8_inter_default;
-            }
-            else  
-              qmatrix[i] = qmatrix[i-2];
-          }
-          else
-          {
-            if(pps->UseDefaultScalingMatrix8x8Flag[i-6])
-              qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;
-            else
-              qmatrix[i] = pps->ScalingList8x8[i-6];
-          }
-        }
-      }
-    }
-  }
-
-  CalculateQuantParam();
-  if(pps->transform_8x8_mode_flag)
-    CalculateQuant8Param();
-}
-
-/*!
- ************************************************************************
- * \brief
- *    For calculating the quantisation values at frame level
- *
- ************************************************************************
- */
-void CalculateQuantParam()
-{
-  int i, j, k, temp;
-
-  for(k=0; k<6; k++)
-    for(i=0; i<4; i++)
-      for(j=0; j<4; j++)
-      {
-        temp = (i<<2)+j;
-        InvLevelScale4x4Luma_Intra[k][i][j]      = dequant_coef[k][i][j] * qmatrix[0][temp];
-        InvLevelScale4x4Chroma_Intra[0][k][i][j] = dequant_coef[k][i][j] * qmatrix[1][temp];
-        InvLevelScale4x4Chroma_Intra[1][k][i][j] = dequant_coef[k][i][j] * qmatrix[2][temp];
-
-        InvLevelScale4x4Luma_Inter[k][i][j]      = dequant_coef[k][i][j] * qmatrix[3][temp];
-        InvLevelScale4x4Chroma_Inter[0][k][i][j] = dequant_coef[k][i][j] * qmatrix[4][temp];
-        InvLevelScale4x4Chroma_Inter[1][k][i][j] = dequant_coef[k][i][j] * qmatrix[5][temp];
-      }
-}
 
 /*!
  ***********************************************************************
@@ -1125,422 +903,236 @@ void CalculateQuantParam()
  *    Luma DC inverse transform
  ***********************************************************************
  */ 
-void itrans_2(ColorPlane pl, ImageParameters *img) //!< image parameters
+void itrans_2(ImageParameters *img, Macroblock *currMB, ColorPlane pl) //!< image parameters
 {
-  static int invLevelScale;
   int i,j;
 
-  int qp, qp_c;
-  int qp_per, qp_rem;
+  int (*cof)[16] = img->cof[pl];
+  int qp_scaled = currMB->qp_scaled[pl];
 
-  if (pl)
-  {
-    int uv = pl - 1;
-    qp = img->qp + dec_picture->chroma_qp_offset[uv];
-    qp = iClip3(-(img->bitdepth_chroma_qp_scale), 51, qp); 
-    qp_c   = (qp < 0)? qp : QP_SCALE_CR[qp-MIN_QP];
-    qp_per = (qp_c + img->bitdepth_chroma_qp_scale)/6;
-    qp_rem = (qp_c + img->bitdepth_chroma_qp_scale)%6;
-    invLevelScale = InvLevelScale4x4Chroma_Intra[uv][qp_rem][0][0];
-  }
-  else
-  {
-    qp_per = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
-    qp_rem = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
-    if( IS_INDEPENDENT(img) )
-    {
-      if( img->colour_plane_id == 0 )
-      {
-        invLevelScale = InvLevelScale4x4Luma_Intra[qp_rem][0][0];
-      }
-      else if( img->colour_plane_id == 1 )
-      {
-        invLevelScale = InvLevelScale4x4Chroma_Intra[0][qp_rem][0][0];
-      }
-      else if( img->colour_plane_id == 2 )
-      {
-        invLevelScale = InvLevelScale4x4Chroma_Intra[1][qp_rem][0][0];
-      }
-    }
-    else
-    {
-      invLevelScale = InvLevelScale4x4Luma_Intra[qp_rem][0][0];
-    }
-  }
+  int qp_per = qp_per_matrix[ qp_scaled ];
+  int qp_rem = qp_rem_matrix[ qp_scaled ];    
+
+  int invLevelScale = InvLevelScale4x4_Intra[pl][qp_rem][0][0];
 
   // horizontal
   for (j=0; j < 4;j++) 
-    for (i=0; i < 4;i++) 
-    {
-      M4[j][i]=img->cof[pl][j<<2][i<<2];
-    }
-
-    ihadamard4x4(M4, M4);
-    // vertical
-
-    for (j=0; j < 4;j++) 
-      for (i=0; i < 4;i++) 
-      {
-        img->cof[pl][j<<2][i<<2] = rshift_rnd((( M4[j][i]*invLevelScale) << qp_per), 6);
-      }
-}
-
-
-
-void itrans_sp(ColorPlane pl, 
-               ImageParameters *img,  //!< image parameters
-               int ioff,             //!< index to 4x4 block
-               int joff)              //!<
-{
-  int i,j,i1,j1;
-  int m5[4];
-  int m6[4];
-  int predicted_block[BLOCK_SIZE][BLOCK_SIZE],ilev;
-
-  int qp_per = (img->qp-MIN_QP)/6;
-  int qp_rem = (img->qp-MIN_QP)%6;
-
-  int qp_per_sp = (img->qpsp-MIN_QP)/6;
-  int qp_rem_sp = (img->qpsp-MIN_QP)%6;
-  int q_bits_sp = Q_BITS+qp_per_sp;
-  int qp_const2 = (1<<q_bits_sp)/2;  //sp_pred
-  imgpel (*mpr)[16] = img->mpr[LumaComp];
-  int    (*m7) [16] = img->m7[LumaComp];
-
-  if (img->type == SI_SLICE) //ES modified
-  {
-    qp_per = (img->qpsp-MIN_QP)/6;
-    qp_rem = (img->qpsp-MIN_QP)%6;
-  }
-
-  for (j=0; j< BLOCK_SIZE; j++)
-  for (i=0; i< BLOCK_SIZE; i++)
-      predicted_block[i][j]=mpr[j+joff][i+ioff];
-  
-  for (j=0; j < BLOCK_SIZE; j++)
-  {
-    for (i=0; i < 2; i++)
-    {
-      i1=3-i;
-      m5[i]  = predicted_block[i][j]+predicted_block[i1][j];
-      m5[i1] = predicted_block[i][j]-predicted_block[i1][j];
-    }
-    predicted_block[0][j]=(m5[0]+m5[1]);
-    predicted_block[2][j]=(m5[0]-m5[1]);
-    predicted_block[1][j]=m5[3]*2+m5[2];
-    predicted_block[3][j]=m5[3]-m5[2]*2;
-  }
-
-  //  Vertical transform
-  for (i=0; i < BLOCK_SIZE; i++)
   {
-    for (j=0; j < 2; j++)
+    for (i=0; i < 4;i++) 
     {
-      j1=3-j;
-      m5[j]=predicted_block[i][j]+predicted_block[i][j1];
-      m5[j1]=predicted_block[i][j]-predicted_block[i][j1];
+      M4[j][i]=cof[j<<2][i<<2];
     }
-    predicted_block[i][0]=(m5[0]+m5[1]);
-    predicted_block[i][2]=(m5[0]-m5[1]);
-    predicted_block[i][1]=m5[3]*2+m5[2];
-    predicted_block[i][3]=m5[3]-m5[2]*2;
   }
 
-  for (j=0;j<BLOCK_SIZE;j++)
-  for (i=0;i<BLOCK_SIZE;i++)
-  {
-    // recovering coefficient since they are already dequantized earlier
-    img->cof[0][joff + j][ioff + i]=(img->cof[0][joff + j][ioff + i] >> qp_per) / dequant_coef[qp_rem][j][i];
-    if(img->sp_switch || img->type==SI_SLICE)  //M.W. patched for SI
-    {
-      ilev=(iabs(predicted_block[i][j]) * quant_coef[qp_rem_sp][i][j] + qp_const2) >> q_bits_sp; //ES added
-      ilev= isignab(ilev,predicted_block[i][j])+ img->cof[0][joff + j][ioff + i];                           //ES added
-      img->cof[0][joff + j][ioff + i] = isignab(iabs(ilev) * dequant_coef[qp_rem_sp][j][i] << qp_per_sp ,ilev) ; //ES added      
-    }                                                                                             //ES added
-    else
-    {                                                                                          //ES added
-      ilev=((img->cof[0][joff + j][ioff + i]*dequant_coef[qp_rem][j][i]*A[i][j]<< qp_per) >>6)+predicted_block[i][j] ;
-      img->cof[0][joff + j][ioff + i]=isignab((iabs(ilev) * quant_coef[qp_rem_sp][i][j] + qp_const2) >> q_bits_sp, ilev) * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
-    }
-  }
-  // horizontal
-  for (j=0;j<BLOCK_SIZE;j++)
-  {
-    for (i=0;i<BLOCK_SIZE;i++)
-    {
-      m5[i]=img->cof[0][joff + j][ioff + i];
-    }
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
+  ihadamard4x4(M4, M4);
 
-    for (i=0;i<2;i++)
-    {
-      i1=3-i;
-      m7[j][i]=m6[i]+m6[i1];
-      m7[j][i1]=m6[i]-m6[i1];
-    }
-  }
   // vertical
-  for (i=0;i<BLOCK_SIZE;i++)
+  for (j=0; j < 4;j++) 
   {
-    for (j=0;j<BLOCK_SIZE;j++)
-      m5[j]=m7[j][i];
-
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
-
-    for (j=0;j<2;j++)
+    for (i=0; i < 4;i++) 
     {
-      j1=3-j;
-      m7[j][i] =iClip1(img->max_imgpel_value,rshift_rnd_sf((m6[j]+m6[j1]),DQ_BITS));
-      m7[j1][i]=iClip1(img->max_imgpel_value,rshift_rnd_sf((m6[j]-m6[j1]),DQ_BITS));
+      cof[j<<2][i<<2] = rshift_rnd((( M4[j][i] * invLevelScale) << qp_per), 6);
     }
   }
 }
 
-/*!
- ***********************************************************************
- * \brief
- *    The routine performs transform,quantization,inverse transform, adds the diff.
- *    to the prediction and writes the result to the decoded luma frame. Includes the
- *    RD constrained quantization also.
- *
- * \par Input:
- *    block_x,block_y: Block position inside a macro block (0,4,8,12).
- *
- * \par Output:
- *    nonzero: 0 if no levels are nonzero.  1 if there are nonzero levels. \n
- *    coeff_cost: Counter for nonzero coefficients, used to discard expencive levels.
- ************************************************************************
- */
-void copyblock_sp(ImageParameters *img,int block_x,int block_y)
-{
-  int i,j,i1,j1,m5[4],m6[4];
 
-  int predicted_block[BLOCK_SIZE][BLOCK_SIZE];
-  int qp_per = (img->qpsp-MIN_QP)/6;
-  int qp_rem = (img->qpsp-MIN_QP)%6;
-  int q_bits    = Q_BITS+qp_per;
-  int qp_const2=(1<<q_bits)/2;  //sp_pred
-  imgpel (*mpr)[16] = img->mpr[LumaComp];
-  int    (*m7) [16] = img->m7[LumaComp];
+void itrans_sp(ImageParameters *img,  //!< image parameters
+               ColorPlane pl, 
+               int ioff,             //!< index to 4x4 block
+               int joff)              //!<
+{
+  int i,j;  
+  int ilev, icof;
 
+  int qp = (img->type == SI_SLICE) ? img->qpsp : img->qp;
+  int qp_per = qp_per_matrix[ qp ];
+  int qp_rem = qp_rem_matrix[ qp ];
 
-  //  Horizontal transform
-  for (j=0; j< BLOCK_SIZE; j++)
-  for (i=0; i< BLOCK_SIZE; i++)
-    predicted_block[i][j]=mpr[j+block_y][i+block_x];
+  int qp_per_sp = qp_per_matrix[ img->qpsp ];
+  int qp_rem_sp = qp_rem_matrix[ img->qpsp ];
+  int q_bits_sp = Q_BITS + qp_per_sp;
 
-  for (j=0; j < BLOCK_SIZE; j++)
-  {
-    for (i=0; i < 2; i++)
-    {
-      i1=3-i;
-      m5[i]=predicted_block[i][j]+predicted_block[i1][j];
-      m5[i1]=predicted_block[i][j]-predicted_block[i1][j];
-    }
-    predicted_block[0][j]=(m5[0]+m5[1]);
-    predicted_block[2][j]=(m5[0]-m5[1]);
-    predicted_block[1][j]=m5[3]*2+m5[2];
-    predicted_block[3][j]=m5[3]-m5[2]*2;
-  }
+  imgpel (*mpr)[16] = img->mb_pred[pl];
+  int    (*m7) [16] = img->mb_rres[pl];
+  int    (*cof)[16] = img->cof[pl];
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
+  
+  //int (*InvLevelScale4x4)[4] = InvLevelScale4x4_Intra[0][qp_rem];
+  const int (*InvLevelScale4x4)  [4] = dequant_coef[qp_rem];
+  const int (*InvLevelScale4x4SP)[4] = dequant_coef[qp_rem_sp];
 
-  //  Vertival transform
 
-  for (i=0; i < BLOCK_SIZE; i++)
-  {
-    for (j=0; j < 2; j++)
-    {
-      j1=3-j;
-      m5[j]=predicted_block[i][j]+predicted_block[i][j1];
-      m5[j1]=predicted_block[i][j]-predicted_block[i][j1];
-    }
-    predicted_block[i][0]=(m5[0]+m5[1]);
-    predicted_block[i][2]=(m5[0]-m5[1]);
-    predicted_block[i][1]=m5[3]*2+m5[2];
-    predicted_block[i][3]=m5[3]-m5[2]*2;
-  }
-
-  // Quant
-  for (j=0;j < BLOCK_SIZE; j++)
-  for (i=0; i < BLOCK_SIZE; i++)
-    m7[j][i]=isignab((iabs(predicted_block[i][j])* quant_coef[qp_rem][i][j]+qp_const2)>> q_bits,predicted_block[i][j])*dequant_coef[qp_rem][j][i]<<qp_per;
+  for (j=0; j< BLOCK_SIZE; j++)
+    for (i=0; i< BLOCK_SIZE; i++)
+      PBlock[j][i] = mpr[j+joff][i+ioff];
 
-  //     IDCT.
-  //     horizontal
+  forward4x4(PBlock, PBlock, 0, 0);
 
-  for (j=0;j<BLOCK_SIZE;j++)
-  {
-    for (i=0;i<BLOCK_SIZE;i++)
-    {
-      m5[i]=m7[j][i];
-    }
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
-
-    for (i=0;i<2;i++)
+  if(img->sp_switch || img->type==SI_SLICE)
+  {    
+    for (j=0;j<BLOCK_SIZE;j++)
     {
-      i1=3-i;
-      m7[j][i]=m6[i]+m6[i1];
-      m7[j][i1]=m6[i]-m6[i1];
+      for (i=0;i<BLOCK_SIZE;i++)
+      {
+        // recovering coefficient since they are already dequantized earlier
+        icof = (cof[joff + j][ioff + i] >> qp_per) / InvLevelScale4x4[j][i];
+        //icof = ((cof[joff + j][ioff + i] * quant_coef[qp_rem][j][i])>> (qp_per + 15)) ;
+        // icof  = rshift_rnd_sf(cof[joff + j][ioff + i] * quant_coef[qp_rem][j][i], qp_per + 15);
+        ilev  = rshift_rnd_sf(iabs(PBlock[j][i]) * quant_coef[qp_rem_sp][j][i], q_bits_sp);
+        ilev  = isignab(ilev, PBlock[j][i]) + icof;
+        cof[joff + j][ioff + i] = ilev * InvLevelScale4x4SP[j][i] << qp_per_sp;
+      }
     }
   }
-  // vertical
-  for (i=0;i<BLOCK_SIZE;i++)
+  else
   {
     for (j=0;j<BLOCK_SIZE;j++)
-      m5[j]=m7[j][i];
-
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
-
-    for (j=0;j<2;j++)
     {
-      j1=3-j;
-      m7[j][i] =iClip1(img->max_imgpel_value,rshift_rnd_sf((m6[j]+m6[j1]),DQ_BITS));
-      m7[j1][i]=iClip1(img->max_imgpel_value,rshift_rnd_sf((m6[j]-m6[j1]),DQ_BITS));
+      for (i=0;i<BLOCK_SIZE;i++)
+      {
+        // recovering coefficient since they are already dequantized earlier
+        icof = (cof[joff + j][ioff + i] >> qp_per) / InvLevelScale4x4[j][i];
+        //icof = cof[joff + j][ioff + i];
+        //icof  = rshift_rnd_sf(cof[joff + j][ioff + i] * quant_coef[qp_rem][j][i], qp_per + 15);
+        ilev = PBlock[j][i] + ((icof * InvLevelScale4x4[j][i] * A[j][i] <<  qp_per) >> 6);
+        ilev  = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][j][i], q_bits_sp);
+        //cof[joff + j][ioff + i] = ilev * InvLevelScale4x4SP[j][i] << qp_per_sp;
+        cof[joff + j][ioff + i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+      }
     }
   }
 
-  //  Decoded block moved to frame memory
-
-  for (j=0; j < BLOCK_SIZE; j++)
-    for (i=0; i < BLOCK_SIZE; i++)
-      dec_picture->imgY[img->pix_y+block_y+j][img->pix_x+block_x+i]=(imgpel) m7[j][i];
+  inverse4x4(cof, m7, joff, ioff);
 
+  for (j=0;j<BLOCK_SIZE;j++)
+    for (i=0;i<BLOCK_SIZE;i++)
+      m7[j + joff][i + ioff] = iClip1(max_imgpel_value,rshift_rnd_sf(m7[j + joff][i + ioff], DQ_BITS));
 }
 
+
 void itrans_sp_cr(ImageParameters *img, int uv)
 {
-  int i,j,i1,j2,ilev,n2,n1,j1,mb_y;
-  int m5[BLOCK_SIZE];
-  int predicted_chroma_block[MB_BLOCK_SIZE/2][MB_BLOCK_SIZE/2],mp1[BLOCK_SIZE];
+  int i,j,ilev, icof, n2,n1;
+  int mp1[BLOCK_SIZE];
   int qp_per,qp_rem;
-  int qp_per_sp,qp_rem_sp,q_bits_sp,qp_const2;
-  imgpel (*mpr)[16] = img->mpr[uv + 1];
+  int qp_per_sp,qp_rem_sp,q_bits_sp;
+  imgpel (*mpr)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1];
+  int    (*cof)[MB_BLOCK_SIZE] = img->cof[uv + 1];
 
-  qp_per    = ((img->qp<0?img->qp:QP_SCALE_CR[img->qp])-MIN_QP)/6;
-  qp_rem    = ((img->qp<0?img->qp:QP_SCALE_CR[img->qp])-MIN_QP)%6;
+  qp_per    = qp_per_matrix[ ((img->qp < 0 ? img->qp : QP_SCALE_CR[img->qp]))];
+  qp_rem    = qp_rem_matrix[ ((img->qp < 0 ? img->qp : QP_SCALE_CR[img->qp]))];
 
-  qp_per_sp    = ((img->qpsp<0?img->qpsp:QP_SCALE_CR[img->qpsp])-MIN_QP)/6;
-  qp_rem_sp    = ((img->qpsp<0?img->qpsp:QP_SCALE_CR[img->qpsp])-MIN_QP)%6;
-  q_bits_sp    = Q_BITS+qp_per_sp;
-  qp_const2=(1<<q_bits_sp)/2;  //sp_pred
+  qp_per_sp = qp_per_matrix[ ((img->qpsp < 0 ? img->qpsp : QP_SCALE_CR[img->qpsp]))];
+  qp_rem_sp = qp_rem_matrix[ ((img->qpsp < 0 ? img->qpsp : QP_SCALE_CR[img->qpsp]))];
+  q_bits_sp = Q_BITS + qp_per_sp;  
 
   if (img->type == SI_SLICE)
   {
-    qp_per    = ((img->qpsp < 0 ? img->qpsp : QP_SCALE_CR[img->qpsp]) - MIN_QP) / 6;
-    qp_rem    = ((img->qpsp < 0 ? img->qpsp : QP_SCALE_CR[img->qpsp]) - MIN_QP) % 6;
+    qp_per = qp_per_sp;
+    qp_rem = qp_rem_sp;
   }
 
-  for (j=0; j < MB_BLOCK_SIZE/2; j++)
-  for (i=0; i < MB_BLOCK_SIZE/2; i++)
+  for (j=0; j < img->mb_cr_size_y; j++)
   {
-    predicted_chroma_block[i][j]=mpr[j][i];
-    mpr[j][i]=0;
+    for (i=0; i < img->mb_cr_size_x; i++)
+    {
+      PBlock[j][i] = mpr[j][i];
+      mpr[j][i] = 0;
+    }
   }
-  for (n2=0; n2 <= BLOCK_SIZE; n2 += BLOCK_SIZE)
+
+  for (n2=0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
   {
-    for (n1=0; n1 <= BLOCK_SIZE; n1 += BLOCK_SIZE)
+    for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
     {
-      //  Horizontal transform.
-      for (j=0; j < BLOCK_SIZE; j++)
+      forward4x4(PBlock, PBlock, n2, n1);
+    }
+  }
+
+  //     2X2 transform of DC coeffs.
+  mp1[0] = (PBlock[0][0] + PBlock[4][0] + PBlock[0][4] + PBlock[4][4]);
+  mp1[1] = (PBlock[0][0] - PBlock[4][0] + PBlock[0][4] - PBlock[4][4]);
+  mp1[2] = (PBlock[0][0] + PBlock[4][0] - PBlock[0][4] - PBlock[4][4]);
+  mp1[3] = (PBlock[0][0] - PBlock[4][0] - PBlock[0][4] + PBlock[4][4]);
+
+  if (img->sp_switch || img->type==SI_SLICE)  
+  {        
+    for (n2=0; n2 < 2; n2 ++)
+    {
+      for (n1=0; n1 < 2; n1 ++)
       {
-        mb_y=n2+j;
-        for (i=0; i < 2; i++)
-        {
-          i1=3-i;
-          m5[i]=predicted_chroma_block[i+n1][mb_y]+predicted_chroma_block[i1+n1][mb_y];
-          m5[i1]=predicted_chroma_block[i+n1][mb_y]-predicted_chroma_block[i1+n1][mb_y];
-        }
-        predicted_chroma_block[n1][mb_y]  =(m5[0]+m5[1]);
-        predicted_chroma_block[n1+2][mb_y]=(m5[0]-m5[1]);
-        predicted_chroma_block[n1+1][mb_y]=m5[3]*2+m5[2];
-        predicted_chroma_block[n1+3][mb_y]=m5[3]-m5[2]*2;
+        //quantization fo predicted block
+        ilev = rshift_rnd_sf(iabs (mp1[n1+n2*2]) * quant_coef[qp_rem_sp][0][0], q_bits_sp + 1);
+        //addition
+        ilev = isignab(ilev, mp1[n1+n2*2]) + cof[n2<<2][n1<<2];
+        //dequantization
+        mp1[n1+n2*2] =ilev * dequant_coef[qp_rem_sp][0][0] << qp_per_sp;
       }
+    }
 
-      //  Vertical transform.
-
-      for (i=0; i < BLOCK_SIZE; i++)
+    for (n2 = 0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
+    {
+      for (n1 = 0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
       {
-        j1=n1+i;
-        for (j=0; j < 2; j++)
+        for (j = 0; j < BLOCK_SIZE; j++)
         {
-          j2=3-j;
-          m5[j]=predicted_chroma_block[j1][n2+j]+predicted_chroma_block[j1][n2+j2];
-          m5[j2]=predicted_chroma_block[j1][n2+j]-predicted_chroma_block[j1][n2+j2];
+          for (i = 0; i < BLOCK_SIZE; i++)
+          {
+            // recovering coefficient since they are already dequantized earlier
+            cof[n2 + j][n1 + i] = (cof[n2 + j][n1 + i] >> qp_per) / dequant_coef[qp_rem][j][i];
+
+            //quantization of the predicted block
+            ilev = rshift_rnd_sf(iabs(PBlock[n2 + j][n1 + i]) * quant_coef[qp_rem_sp][j][i], q_bits_sp);
+            //addition of the residual
+            ilev = isignab(ilev,PBlock[n2 + j][n1 + i]) + cof[n2 + j][n1 + i];
+            // Inverse quantization
+            cof[n2 + j][n1 + i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+          }
         }
-        predicted_chroma_block[j1][n2+0]=(m5[0]+m5[1]);
-        predicted_chroma_block[j1][n2+2]=(m5[0]-m5[1]);
-        predicted_chroma_block[j1][n2+1]=m5[3]*2+m5[2];
-        predicted_chroma_block[j1][n2+3]=m5[3]-m5[2]*2;
       }
     }
   }
-
-  //     2X2 transform of DC coeffs.
-  mp1[0]=(predicted_chroma_block[0][0]+predicted_chroma_block[4][0]+predicted_chroma_block[0][4]+predicted_chroma_block[4][4]);
-  mp1[1]=(predicted_chroma_block[0][0]-predicted_chroma_block[4][0]+predicted_chroma_block[0][4]-predicted_chroma_block[4][4]);
-  mp1[2]=(predicted_chroma_block[0][0]+predicted_chroma_block[4][0]-predicted_chroma_block[0][4]-predicted_chroma_block[4][4]);
-  mp1[3]=(predicted_chroma_block[0][0]-predicted_chroma_block[4][0]-predicted_chroma_block[0][4]+predicted_chroma_block[4][4]);
-
-  for (n1=0; n1 < 2; n1 ++)
-  for (n2=0; n2 < 2; n2 ++)
+  else
   {
-    if (img->sp_switch || img->type==SI_SLICE)  //M.W. patched for SI
-    {
-      //quantization fo predicted block
-      ilev=(iabs (mp1[n1+n2*2]) * quant_coef[qp_rem_sp][0][0] + 2 * qp_const2) >> (q_bits_sp + 1);
-      //addition
-      ilev=img->cof[uv + 1][n2<<2][n1<<2]+isignab(ilev,mp1[n1+n2*2]);
-      //dequantization
-      mp1[n1+n2*2] =ilev*dequant_coef[qp_rem_sp][0][0]<<qp_per_sp;
-    }
-    else
+    for (n2=0; n2 < 2; n2 ++)
     {
-      ilev=((img->cof[uv + 1][n2<<2][n1<<2]*dequant_coef[qp_rem][0][0]*A[0][0]<< qp_per) >>5)+mp1[n1+n2*2];
-      mp1[n1+n2*2]=isignab((iabs(ilev)* quant_coef[qp_rem_sp][0][0]+ 2 * qp_const2)>> (q_bits_sp+1),ilev)*dequant_coef[qp_rem_sp][0][0]<<qp_per_sp;
+      for (n1=0; n1 < 2; n1 ++)
+      {
+        ilev = mp1[n1+n2*2] + (((cof[n2<<2][n1<<2] * dequant_coef[qp_rem][0][0] * A[0][0]) << qp_per) >> 5);
+        ilev = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][0][0], q_bits_sp + 1);
+        //ilev = isignab(rshift_rnd_sf(iabs(ilev)* quant_coef[qp_rem_sp][0][0], q_bits_sp + 1), ilev);
+        mp1[n1+n2*2] = ilev * dequant_coef[qp_rem_sp][0][0] << qp_per_sp;
+      }
     }
-  }
 
-
-  for (n2=0; n2 < 2; n2 ++)
-  for (n1=0; n1 < 2; n1 ++)
-  for (i=0;i< BLOCK_SIZE; i++)
-  for (j=0;j< BLOCK_SIZE; j++)
-  {
-  // recovering coefficient since they are already dequantized earlier
-    img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i] = (img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i] >> qp_per) / dequant_coef[qp_rem][j][i];
-
-    if (img->sp_switch || img->type==SI_SLICE)  //M.W. patched for SI
+    for (n2 = 0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
     {
-      //quantization of the predicted block
-      ilev =  (iabs(predicted_chroma_block[n1*BLOCK_SIZE+i][n2*BLOCK_SIZE+j]) * quant_coef[qp_rem_sp][i][j] + qp_const2) >> q_bits_sp;
-      //addition of the residual
-      ilev = isignab(ilev,predicted_chroma_block[n1*BLOCK_SIZE+i][n2*BLOCK_SIZE+j]) + img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i];
-      // Inverse quantization
-      img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
-    }
-    else
-    {
-      //dequantization and addition of the predicted block      
-      ilev=((img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i]*dequant_coef[qp_rem][j][i]*A[i][j]<< qp_per) >>6)+predicted_chroma_block[n1*BLOCK_SIZE+i][n2*BLOCK_SIZE+j] ;
-      //quantization and dequantization            
-      img->cof[uv + 1][(n2<<2) + j][(n1<<2) + i] = isignab((iabs(ilev) * quant_coef[qp_rem_sp][i][j] + qp_const2)>> q_bits_sp,ilev)*dequant_coef[qp_rem_sp][j][i]<<qp_per_sp;
+      for (n1 = 0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
+      {
+        for (j = 0; j< BLOCK_SIZE; j++)
+        {
+          for (i = 0; i< BLOCK_SIZE; i++)
+          {
+            // recovering coefficient since they are already dequantized earlier
+            //icof = ((((cof[n2 + j][n1 + i] << 4) + qp_per/2)>> qp_per) + dequant_coef[qp_rem][j][i]/2) / dequant_coef[qp_rem][j][i];
+            icof = (cof[n2 + j][n1 + i] >> qp_per) / dequant_coef[qp_rem][j][i];
+            //dequantization and addition of the predicted block      
+            ilev = PBlock[n2 + j][n1 + i] + ((icof * dequant_coef[qp_rem][j][i] * A[j][i] << qp_per) >> 6);
+            //quantization and dequantization
+            ilev = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][j][i], q_bits_sp);
+            cof[n2 + j][n1 + i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+            //printf( " %d %d %d\n", j, i, quant_coef[qp_rem_sp][j][i]);
+          }
+        }
+      }
     }
   }
-  img->cof[uv+1][0][0] = (mp1[0] + mp1[1] + mp1[2] + mp1[3]) >> 1;
-  img->cof[uv+1][0][4] = (mp1[0] + mp1[1] - mp1[2] - mp1[3]) >> 1;
-  img->cof[uv+1][4][0] = (mp1[0] - mp1[1] + mp1[2] - mp1[3]) >> 1;
-  img->cof[uv+1][4][4] = (mp1[0] - mp1[1] - mp1[2] + mp1[3]) >> 1;
+
+  cof[0][0] = (mp1[0] + mp1[1] + mp1[2] + mp1[3]) >> 1;
+  cof[0][4] = (mp1[0] + mp1[1] - mp1[2] - mp1[3]) >> 1;
+  cof[4][0] = (mp1[0] - mp1[1] + mp1[2] - mp1[3]) >> 1;
+  cof[4][4] = (mp1[0] - mp1[1] - mp1[2] + mp1[3]) >> 1;
 }
 
 static const byte decode_block_scan[16] = {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
@@ -1551,7 +1143,7 @@ void iMBtrans4x4(ColorPlane pl, ImageParameters *img, int smb)
   int jj, ii;
   int block8x8;
   int i, j, k;  
-  int    (*m7) [16] = img->m7[pl];
+  int    (*m7) [16] = img->mb_rres[pl];
   imgpel **curr_img = pl ? &(dec_picture->imgUV[pl - 1][img->pix_y]): &dec_picture->imgY[img->pix_y];
 
   //For residual DPCM
@@ -1571,7 +1163,7 @@ void iMBtrans4x4(ColorPlane pl, ImageParameters *img, int smb)
       jj = ((decode_block_scan[k] >> 2) & 3) << BLOCK_SHIFT;
       ii = (decode_block_scan[k] & 3) << BLOCK_SHIFT;
 
-      itrans_4x4(pl, img, ii, jj);   // use DCT transform and make 4x4 block m7 from prediction block mpr
+      itrans_4x4(img, pl, ii, jj);   // use DCT transform and make 4x4 block m7 from prediction block mpr
       
       for(j = jj; j < jj + BLOCK_SIZE; j++)
       {
@@ -1584,10 +1176,10 @@ void iMBtrans4x4(ColorPlane pl, ImageParameters *img, int smb)
   }
 }
 
-void iMBtrans8x8(ColorPlane pl, ImageParameters *img)
+void iMBtrans8x8(ImageParameters *img,  Macroblock *currMB, ColorPlane pl)
 {
   imgpel **curr_img = pl ? &dec_picture->imgUV[pl - 1][img->pix_y]: &dec_picture->imgY[img->pix_y];
-  int    (*m7)[16] = img->m7[pl];
+  int    (*m7)[MB_BLOCK_SIZE] = img->mb_rres[pl];
   int block8x8;
   int i,j;
   int ioff, joff;
@@ -1599,7 +1191,7 @@ void iMBtrans8x8(ColorPlane pl, ImageParameters *img)
     ioff = 8 * (block8x8 & 0x01);
     joff = 8 * (block8x8 >> 1);
 
-    itrans8x8(pl, img, ioff, joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
+    itrans8x8(img, currMB, pl, ioff, joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
 
     for(j = joff; j < joff + 8; j++)
     {
@@ -1611,7 +1203,7 @@ void iMBtrans8x8(ColorPlane pl, ImageParameters *img)
   }
 }
 
-void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int need_4x4_transform, int smb)
+void iTransform(ImageParameters *img,  Macroblock *currMB, ColorPlane pl, int need_4x4_transform, int smb)
 {
   static imgpel (*mpr) [16];
   static imgpel **curr_img;
@@ -1625,16 +1217,16 @@ void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int ne
     }
     else // 8x8 inverse transform
     {  
-      iMBtrans8x8(pl, img);    
+      iMBtrans8x8(img, currMB, pl);    
     }
   }
   else
   {
-    mpr = img->mpr[pl]; 
+    mpr = img->mb_pred[pl]; 
     curr_img = pl ? &dec_picture->imgUV[uv][img->pix_y] : &dec_picture->imgY[img->pix_y];
     for(j = 0; j < MB_BLOCK_SIZE; j++)
     { 
-      memcpy(&(curr_img[j][img->pix_x]), &(img->mpr[pl][j][0]), MB_BLOCK_SIZE * sizeof(imgpel));
+      memcpy(&(curr_img[j][img->pix_x]), &(img->mb_pred[pl][j][0]), MB_BLOCK_SIZE * sizeof(imgpel));
     }
   }
 
@@ -1653,7 +1245,7 @@ void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int ne
       // =============== 4x4 itrans ================
       // -------------------------------------------
       curUV = &dec_picture->imgUV[uv][img->pix_c_y]; 
-      m7UV  = img->m7[uv+1];
+      m7UV  = img->mb_rres[uv+1];
 
       if (!smb && (currMB->cbp>>4))
       {
@@ -1664,7 +1256,7 @@ void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int ne
             joff = subblk_offset_y[1][b8][b4];
             ioff = subblk_offset_x[1][b8][b4];
 
-            itrans_4x4((ColorPlane) (uv + 1), img, ioff, joff);
+            itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
 
             for(jj=joff;jj<joff + 4;jj++)
             {
@@ -1682,11 +1274,11 @@ void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int ne
       {
         itrans_sp_cr(img, uv);
 
-        for (joff=0;joff<8;joff+=4)
+        for (joff = 0; joff < img->mb_cr_size_y; joff += BLOCK_SIZE)
         {
-          for(ioff=0;ioff<8;ioff+=4)
+          for(ioff = 0; ioff < img->mb_cr_size_x ;ioff += BLOCK_SIZE)
           {
-            itrans_4x4((ColorPlane) (uv + 1), img, ioff, joff);
+            itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
 
             for(jj=joff;jj<joff + 4;jj++)
               for(ii=ioff;ii<ioff + 4;ii++)
@@ -1698,7 +1290,7 @@ void iTransform(Macroblock *currMB, ColorPlane pl, ImageParameters *img,  int ne
       }
       else 
       {
-        mpr = img->mpr[uv + 1];
+        mpr = img->mb_pred[uv + 1];
         for(jj = 0; jj < img->mb_size[1][1]; jj++)
           memcpy(&(curUV[jj][img->pix_c_x]), &(mpr[jj][0]), img->mb_size[1][0] * sizeof(imgpel));
       }
diff --git a/ldecod/src/cabac.c b/ldecod/src/cabac.c
index 96df570..a85e457 100644
--- a/ldecod/src/cabac.c
+++ b/ldecod/src/cabac.c
@@ -123,8 +123,6 @@ void delete_contexts_MotionInfo(MotionInfoContexts *deco_ctx)
     return;
 
   free( deco_ctx );
-
-  return;
 }
 
 
@@ -141,28 +139,17 @@ void delete_contexts_TextureInfo(TextureInfoContexts *deco_ctx)
     return;
 
   free( deco_ctx );
-
-  return;
 }
 
 void readFieldModeInfo_CABAC( SyntaxElement *se,
                               ImageParameters *img,
                               DecodingEnvironmentPtr dep_dp)
-{
-  int a,b,act_ctx;
+{  
   MotionInfoContexts *ctx         = (img->currentSlice)->mot_ctx;
   Macroblock         *currMB      = &img->mb_data[img->current_mb_nr];
-
-  if (currMB->mbAvailA)
-    a = img->mb_data[currMB->mbAddrA].mb_field;
-  else
-    a = 0;
-  if (currMB->mbAvailB)
-    b = img->mb_data[currMB->mbAddrB].mb_field;
-  else
-    b=0;
-
-  act_ctx = a + b;
+  int a = currMB->mbAvailA ? img->mb_data[currMB->mbAddrA].mb_field : 0;
+  int b = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
+  int act_ctx = a + b;
 
   se->value1 = biari_decode_symbol (dep_dp, &ctx->mb_aff_contexts[act_ctx]);
 
@@ -270,7 +257,7 @@ void readMVD_CABAC( SyntaxElement *se,
 {
   int i = img->subblock_x << 2;
   int j = img->subblock_y << 2;
-  int a, b;
+  int a = 0, b = 0;
   int act_ctx;
   int act_sym;
   int mv_local_err;
@@ -297,8 +284,6 @@ void readMVD_CABAC( SyntaxElement *se,
         b /= 2;
     }
   }
-  else
-    b=0;
 
   if (block_a.available)
   {
@@ -311,8 +296,6 @@ void readMVD_CABAC( SyntaxElement *se,
         a /= 2;
     }
   }
-  else
-    a = 0;
 
   if ((mv_local_err=a+b)<3)
     act_ctx = 5*k;
@@ -438,25 +421,16 @@ void readB8_typeInfo_CABAC (SyntaxElement *se,
 void readMB_skip_flagInfo_CABAC( SyntaxElement *se,
                                  ImageParameters *img,
                                  DecodingEnvironmentPtr dep_dp)
-{
-  int a, b;
-  int act_ctx;
+{  
   int bframe=(img->type==B_SLICE);
   MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
-
+  int a = (currMB->mb_available_left != NULL) ? (currMB->mb_available_left->skip_flag == 0) : 0;
+  int b = (currMB->mb_available_up   != NULL) ? (currMB->mb_available_up  ->skip_flag == 0) : 0;
+  int act_ctx;
 
   if (bframe)
   {
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
-      b = (currMB->mb_available_up->skip_flag==0 ? 1 : 0);
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
-      a = (currMB->mb_available_left->skip_flag==0 ? 1 : 0);
-
     act_ctx = 7 + a + b;
 
     if (biari_decode_symbol (dep_dp, &ctx->mb_type_contexts[2][act_ctx]) == 1)
@@ -466,15 +440,6 @@ void readMB_skip_flagInfo_CABAC( SyntaxElement *se,
   }
   else
   {
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
-      b = (( (currMB->mb_available_up)->skip_flag == 0) ? 1 : 0 );
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
-      a = (( (currMB->mb_available_left)->skip_flag == 0) ? 1 : 0 );
-
     act_ctx = a + b;
 
     if (biari_decode_symbol(dep_dp, &ctx->mb_type_contexts[1][act_ctx]) == 1)
@@ -492,7 +457,6 @@ void readMB_skip_flagInfo_CABAC( SyntaxElement *se,
   {
     last_dquant=0;
   }
-  return;
 }
 
 /*!
@@ -539,7 +503,7 @@ void readMB_typeInfo_CABAC( SyntaxElement *se,
   MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
 
-  int a, b;
+  int a = 0, b = 0;
   int act_ctx;
   int act_sym;
   int bframe=(img->type==B_SLICE);
@@ -549,14 +513,10 @@ void readMB_typeInfo_CABAC( SyntaxElement *se,
 
   if(img->type == I_SLICE)  // INTRA-frame
   {
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
+    if (currMB->mb_available_up != NULL)
       b = (((currMB->mb_available_up)->mb_type != I4MB && currMB->mb_available_up->mb_type != I8MB) ? 1 : 0 );
 
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
+    if (currMB->mb_available_left != NULL)
       a = (((currMB->mb_available_left)->mb_type != I4MB && currMB->mb_available_left->mb_type != I8MB) ? 1 : 0 );
 
     act_ctx = a + b;
@@ -605,13 +565,10 @@ void readMB_typeInfo_CABAC( SyntaxElement *se,
   else if(img->type == SI_SLICE)  // SI-frame
   {
     // special ctx's for SI4MB
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
+    if (currMB->mb_available_up != NULL)
       b = (( (currMB->mb_available_up)->mb_type != SI4MB) ? 1 : 0 );
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
+
+    if (currMB->mb_available_left != NULL)
       a = (( (currMB->mb_available_left)->mb_type != SI4MB) ? 1 : 0 );
 
     act_ctx = a + b;
@@ -624,20 +581,16 @@ void readMB_typeInfo_CABAC( SyntaxElement *se,
     }
     else // analog INTRA_IMG
     {
-      if (currMB->mb_available_up == NULL)
-        b = 0;
-      else
+      if (currMB->mb_available_up != NULL)
         b = (( (currMB->mb_available_up)->mb_type != I4MB) ? 1 : 0 );
-      if (currMB->mb_available_left == NULL)
-        a = 0;
-      else
+
+      if (currMB->mb_available_left != NULL)
         a = (( (currMB->mb_available_left)->mb_type != I4MB) ? 1 : 0 );
 
       act_ctx = a + b;
       act_sym = biari_decode_symbol(dep_dp, ctx->mb_type_contexts[0] + act_ctx);
       se->context = act_ctx; // store context
 
-
       if (act_sym==0) // 4x4 Intra
       {
         curr_mb_type = 1;
@@ -682,13 +635,10 @@ void readMB_typeInfo_CABAC( SyntaxElement *se,
   {
     if (bframe)
     {
-      if (currMB->mb_available_up == NULL)
-        b = 0;
-      else
+      if (currMB->mb_available_up != NULL)
         b = (( (currMB->mb_available_up)->mb_type != 0) ? 1 : 0 );
-      if (currMB->mb_available_left == NULL)
-        a = 0;
-      else
+
+      if (currMB->mb_available_left != NULL)
         a = (( (currMB->mb_available_left)->mb_type != 0) ? 1 : 0 );
 
       act_ctx = a + b;
@@ -851,12 +801,13 @@ void readRefFrame_CABAC( SyntaxElement *se,
 {
   MotionInfoContexts *ctx = img->currentSlice->mot_ctx;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
+  Macroblock *neighborMB = NULL;
 
   int   addctx  = 0;
-  int   a, b;
+  int   a = 0, b = 0;
   int   act_ctx;
   int   act_sym;
-  char** refframe_array = dec_picture->ref_idx[se->value2];
+  char** refframe_array = dec_picture->motion.ref_idx[se->value2];
   int   b8a, b8b;
 
   PixelPos block_a, block_b;
@@ -867,31 +818,31 @@ void readRefFrame_CABAC( SyntaxElement *se,
   b8a=((block_a.x>>1)&0x01)+2*((block_a.y>>1)&0x01);
   b8b=((block_b.x>>1)&0x01)+2*((block_b.y>>1)&0x01);
 
-  if (!block_b.available)
-    b=0;
-  else if ( (img->mb_data[block_b.mb_addr].mb_type==IPCM) || IS_DIRECT(&img->mb_data[block_b.mb_addr]) || (img->mb_data[block_b.mb_addr].b8mode[b8b]==0 && img->mb_data[block_b.mb_addr].b8pdir[b8b]==2))
-    b=0;
-  else
+  if (block_b.available)
   {
-    if (img->MbaffFrameFlag && (currMB->mb_field == 0) && (img->mb_data[block_b.mb_addr].mb_field == 1))
-      b = (refframe_array[block_b.pos_y][block_b.pos_x] > 1 ? 1 : 0);
-    else
-      b = (refframe_array[block_b.pos_y][block_b.pos_x] > 0 ? 1 : 0);
+    neighborMB = &img->mb_data[block_b.mb_addr];
+    if (!( (neighborMB->mb_type==IPCM) || IS_DIRECT(neighborMB) || (neighborMB->b8mode[b8b]==0 && neighborMB->b8pdir[b8b]==2)))
+    {
+      if (img->MbaffFrameFlag && (currMB->mb_field == 0) && (neighborMB->mb_field == 1))
+        b = (refframe_array[block_b.pos_y][block_b.pos_x] > 1 ? 2 : 0);
+      else
+        b = (refframe_array[block_b.pos_y][block_b.pos_x] > 0 ? 2 : 0);
+    }
   }
 
-  if (!block_a.available)
-    a=0;
-  else if ((img->mb_data[block_a.mb_addr].mb_type==IPCM) || IS_DIRECT(&img->mb_data[block_a.mb_addr]) || (img->mb_data[block_a.mb_addr].b8mode[b8a]==0 && img->mb_data[block_a.mb_addr].b8pdir[b8a]==2))
-    a=0;
-  else
+  if (block_a.available)
   {
-    if (img->MbaffFrameFlag && (currMB->mb_field == 0) && (img->mb_data[block_a.mb_addr].mb_field == 1))
-      a = (refframe_array[block_a.pos_y][block_a.pos_x] > 1 ? 1 : 0);
-    else
-      a = (refframe_array[block_a.pos_y][block_a.pos_x] > 0 ? 1 : 0);
+    neighborMB = &img->mb_data[block_a.mb_addr];
+    if (!((neighborMB->mb_type==IPCM) || IS_DIRECT(neighborMB) || (neighborMB->b8mode[b8a]==0 && neighborMB->b8pdir[b8a]==2)))
+    {
+      if (img->MbaffFrameFlag && (currMB->mb_field == 0) && (neighborMB->mb_field == 1))
+        a = (refframe_array[block_a.pos_y][block_a.pos_x] > 1 ? 1 : 0);
+      else
+        a = (refframe_array[block_a.pos_y][block_a.pos_x] > 0 ? 1 : 0);
+    }
   }
 
-  act_ctx = a + 2*b;
+  act_ctx = a + b;
   se->context = act_ctx; // store context
 
   act_sym = biari_decode_symbol(dep_dp,ctx->ref_no_contexts[addctx] + act_ctx );
@@ -924,14 +875,10 @@ void readDquant_CABAC( SyntaxElement *se,
                        DecodingEnvironmentPtr dep_dp)
 {
   MotionInfoContexts *ctx = img->currentSlice->mot_ctx;
+  int *dquant = &se->value1;
+  int act_ctx = ((last_dquant != 0) ? 1 : 0);
+  int act_sym = biari_decode_symbol(dep_dp,ctx->delta_qp_contexts + act_ctx );
 
-  int act_ctx;
-  int act_sym;
-  int dquant;
-
-  act_ctx = ( (last_dquant != 0) ? 1 : 0);
-
-  act_sym = biari_decode_symbol(dep_dp,ctx->delta_qp_contexts + act_ctx );
   if (act_sym != 0)
   {
     act_ctx = 2;
@@ -939,12 +886,11 @@ void readDquant_CABAC( SyntaxElement *se,
     act_sym++;
   }
 
-  dquant = (act_sym + 1)/2;
+  *dquant = (act_sym + 1) >> 1;
   if((act_sym & 0x01)==0)                           // lsb is signed bit
-    dquant = -dquant;
-  se->value1 = dquant;
+    *dquant = -*dquant;
 
-  last_dquant = dquant;
+  last_dquant = *dquant;
 
 #if TRACE
   fprintf(p_trace, "@%-6d %-63s (%3d)\n",symbolCount++, se->tracestring, se->value1);
@@ -964,6 +910,7 @@ void readCBP_CABAC(SyntaxElement *se,
 {
   TextureInfoContexts *ctx = img->currentSlice->tex_ctx;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
+  Macroblock *neighborMB = NULL;
 
   int mb_x, mb_y;
   int a, b;
@@ -976,23 +923,24 @@ void readCBP_CABAC(SyntaxElement *se,
   //  coding of luma part (bit by bit)
   for (mb_y=0; mb_y < 4; mb_y += 2)
   {
+    if (mb_y == 0)
+    {
+      neighborMB = currMB->mb_available_up;
+      b = 0;
+    }
+
     for (mb_x=0; mb_x < 4; mb_x += 2)
     {
       if (mb_y == 0)
       {
-        if (currMB->mb_available_up == NULL)
-          b = 0;
-        else
+        if (neighborMB != NULL)
         {
-          if((currMB->mb_available_up)->mb_type==IPCM)
-            b=0;
-          else
-            b = (( ((currMB->mb_available_up)->cbp & (1<<(2 + (mb_x>>1)))) == 0) ? 1 : 0);
+          if(neighborMB->mb_type!=IPCM)
+            b = (( (neighborMB->cbp & (1<<(2 + (mb_x>>1)))) == 0) ? 2 : 0);
         }
-
       }
       else
-        b = ( ((cbp & (1<<(mb_x/2))) == 0) ? 1: 0);
+        b = ( ((cbp & (1<<(mb_x/2))) == 0) ? 2: 0);
 
       if (mb_x == 0)
       {
@@ -1000,7 +948,7 @@ void readCBP_CABAC(SyntaxElement *se,
         if (block_a.available)
         {
           if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
-            a=0;
+            a = 0;
           else
             a = (( (img->mb_data[block_a.mb_addr].cbp & (1<<(2*(block_a.y/2)+1))) == 0) ? 1 : 0);
         }
@@ -1010,10 +958,11 @@ void readCBP_CABAC(SyntaxElement *se,
       else
         a = ( ((cbp & (1<<mb_y)) == 0) ? 1: 0);
 
-      curr_cbp_ctx = a+2*b;
-      mask = (1<<(mb_y+mb_x/2));
+      curr_cbp_ctx = a + b;
+      mask = (1 << (mb_y + (mb_x >> 1)));
       cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[0] + curr_cbp_ctx );
-      if (cbp_bit) cbp += mask;
+      if (cbp_bit) 
+        cbp += mask;
     }
   }
 
@@ -1022,53 +971,46 @@ void readCBP_CABAC(SyntaxElement *se,
     // coding of chroma part
     // CABAC decoding for BinIdx 0
     b = 0;
-    if (currMB->mb_available_up != NULL)
+    neighborMB = currMB->mb_available_up;
+    if (neighborMB != NULL)
     {
-      if((currMB->mb_available_up)->mb_type==IPCM)
-        b=1;
-      else
-        b = ((currMB->mb_available_up)->cbp > 15) ? 1 : 0;
+      if (neighborMB->mb_type==IPCM || (neighborMB->cbp > 15))
+        b = 2;
     }
 
     a = 0;
-    if (currMB->mb_available_left != NULL)
+    neighborMB = currMB->mb_available_left;
+    if (neighborMB != NULL)
     {
-      if((currMB->mb_available_left)->mb_type==IPCM)
-        a=1;
-      else
-        a = ((currMB->mb_available_left)->cbp > 15) ? 1 : 0;
+      if (neighborMB->mb_type==IPCM || (neighborMB->cbp > 15))
+        a = 1;
     }
 
-
-    curr_cbp_ctx = a+2*b;
+    curr_cbp_ctx = a + b;
     cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[1] + curr_cbp_ctx );
 
     // CABAC decoding for BinIdx 1
     if (cbp_bit) // set the chroma bits
     {
       b = 0;
-      if (currMB->mb_available_up != NULL)
+      neighborMB = currMB->mb_available_up;
+      if (neighborMB != NULL)
       {
-        if((currMB->mb_available_up)->mb_type==IPCM)
-          b=1;
-        else
-          if ((currMB->mb_available_up)->cbp > 15)
-            b = (( ((currMB->mb_available_up)->cbp >> 4) == 2) ? 1 : 0);
+        //if ((neighborMB->mb_type == IPCM) || ((neighborMB->cbp > 15) && ((neighborMB->cbp >> 4) == 2)))
+        if ((neighborMB->mb_type == IPCM) || ((neighborMB->cbp >> 4) == 2))
+          b = 2;
       }
 
 
       a = 0;
-      if (currMB->mb_available_left != NULL)
+      neighborMB = currMB->mb_available_left;
+      if (neighborMB != NULL)
       {
-        if((currMB->mb_available_left)->mb_type==IPCM)
-          a=1;
-        else
-          if ((currMB->mb_available_left)->cbp > 15)
-            a = (( ((currMB->mb_available_left)->cbp >> 4) == 2) ? 1 : 0);
+        if ((neighborMB->mb_type == IPCM) || ((neighborMB->cbp >> 4) == 2))
+          a = 1;
       }
 
-
-      curr_cbp_ctx = a+2*b;
+      curr_cbp_ctx = a + b;
       cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[2] + curr_cbp_ctx );
       cbp += (cbp_bit == 1) ? 32 : 16;
     }
@@ -1098,33 +1040,21 @@ void readCIPredMode_CABAC(SyntaxElement *se,
                           ImageParameters *img,
                           DecodingEnvironmentPtr dep_dp)
 {
-
   TextureInfoContexts *ctx = img->currentSlice->tex_ctx;
-  Macroblock          *currMB  = &img->mb_data[img->current_mb_nr];
-  int                 act_ctx,a,b;
-  int                 act_sym  = se->value1;
+  Macroblock          *currMB  = &img->mb_data[img->current_mb_nr];  
+  int                 *act_sym  = &se->value1;
 
   Macroblock          *MbUp   = currMB->mb_available_up;
   Macroblock          *MbLeft = currMB->mb_available_left;
 
-  if (MbUp == NULL) 
-    b = 0;
-  else 
-    b = ((MbUp->c_ipred_mode != 0) && (MbUp->mb_type != IPCM)) ? 1 : 0;
-
-  if (MbLeft == NULL)
-    a = 0;
-  else
-    a =  ((MbLeft->c_ipred_mode != 0) && (MbLeft->mb_type != IPCM)) ? 1 : 0;
-
-  act_ctx = a+b;
-
-  act_sym = biari_decode_symbol(dep_dp, ctx->cipr_contexts + act_ctx );
+  int b = (MbUp != NULL)   ? (((MbUp->c_ipred_mode   != 0) && (MbUp->mb_type != IPCM)) ? 1 : 0) : 0;
+  int a = (MbLeft != NULL) ? (((MbLeft->c_ipred_mode != 0) && (MbLeft->mb_type != IPCM)) ? 1 : 0) : 0;
+  int act_ctx = a + b;
 
-  if (act_sym!=0)
-    act_sym = unary_bin_max_decode(dep_dp,ctx->cipr_contexts+3,0,2)+1;
+  *act_sym = biari_decode_symbol(dep_dp, ctx->cipr_contexts + act_ctx );
 
-  se->value1 = act_sym;
+  if (*act_sym != 0)
+    *act_sym = unary_bin_max_decode(dep_dp, ctx->cipr_contexts + 3, 0, 1) + 1;
 
 #if TRACE
   fprintf(p_trace, "@%-6d %-63s (%3d)\n",symbolCount++, se->tracestring, se->value1);
@@ -1307,9 +1237,7 @@ int read_and_store_CBP_block_bit (Macroblock              *currMB,
     //===== encode symbol =====
     cbp_bit = biari_decode_symbol (dep_dp, img->currentSlice->tex_ctx->bcbp_contexts[type2ctx_bcbp[type]] + ctx);
   }
-  
-  
-  
+ 
   //--- set bits for current block ---
   bit         = (y_dc ? 0 : y_ac ? 1+4*j+i : u_dc ? 17 : v_dc ? 18 : u_ac ? 19+4*j+i : 35+4*j+i); 
 
@@ -1414,7 +1342,6 @@ static const int* pos2ctx_map_int[] = {pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_m
                                        pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8i,pos2ctx_map8x4i,
                                        pos2ctx_map8x4i,pos2ctx_map4x4};
 
-
 //===== position -> ctx for LAST =====
 static const int  pos2ctx_last8x8 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
                                          2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
@@ -1451,7 +1378,7 @@ int read_significance_map (Macroblock              *currMB,
   int   i, sig;
   int   coeff_ctr = 0;
   int   i0        = 0;
-  int   i1        = maxpos[type] + 1;
+  int   i1        = maxpos[type];
 
   int               fld       = ( img->structure!=FRAME || currMB->mb_field );
   const int **pos2ctx_Map = (fld) ? pos2ctx_map_int : pos2ctx_map;
@@ -1465,7 +1392,7 @@ int read_significance_map (Macroblock              *currMB,
     i0++; i1++; coeff--;
   }
 
-  for (i=i0; i < i1 - 1; i++) // if last coeff is reached, it has to be significant
+  for (i=i0; i < i1; i++) // if last coeff is reached, it has to be significant
   {
     //--- read significance symbol ---
     sig = biari_decode_symbol   (dep_dp, map_ctx + pos2ctx_Map [type][i]);
@@ -1477,8 +1404,8 @@ int read_significance_map (Macroblock              *currMB,
       //--- read last coefficient symbol ---
       if (biari_decode_symbol (dep_dp, last_ctx + pos2ctx_last[type][i]))
       {
-        for (i++; i < i1; i++) 
-          coeff[i] = 0;
+        memset(&coeff[i + 1], 0, (i1 - i) * sizeof(int));
+        i = i1;
       }
     }
     else
@@ -1487,7 +1414,7 @@ int read_significance_map (Macroblock              *currMB,
     }
   }
   //--- last coefficient must be significant if no last symbol was received ---
-  if (i < i1)
+  if (i < i1 + 1)
   {
     coeff[i] = 1;
     coeff_ctr++;
@@ -1505,16 +1432,15 @@ int read_significance_map (Macroblock              *currMB,
  ************************************************************************
  */
 void read_significant_coefficients (DecodingEnvironmentPtr  dep_dp,
-                                    ImageParameters          *img,
+                                    TextureInfoContexts    *tex_ctx,
                                     int                     type,
                                     int                     coeff[])
 {
   int   i, ctx;
   int   c1 = 1;
   int   c2 = 0;
-  BiContextType *one_contexts = img->currentSlice->tex_ctx->one_contexts[type2ctx_one[type]];
-  BiContextType *abs_contexts = img->currentSlice->tex_ctx->abs_contexts[type2ctx_abs[type]];
-
+  BiContextType *one_contexts = tex_ctx->one_contexts[type2ctx_one[type]];
+  BiContextType *abs_contexts = tex_ctx->abs_contexts[type2ctx_abs[type]];
 
   for (i=maxpos[type]; i>=0; i--)
   {
@@ -1567,7 +1493,7 @@ void readRunLevel_CABAC (SyntaxElement  *se,
       coeff_ctr = read_significance_map (currMB, dep_dp, img, se->context, coeff);
 
       //===== decode significant coefficients =====
-      read_significant_coefficients     (dep_dp, img, se->context, coeff);
+      read_significant_coefficients     (dep_dp, img->currentSlice->tex_ctx, se->context, coeff);
     }
   }
 
@@ -1592,8 +1518,6 @@ void readRunLevel_CABAC (SyntaxElement  *se,
 #endif
 }
 
-
-
 /*!
  ************************************************************************
  * \brief
@@ -1606,9 +1530,11 @@ int readSyntaxElement_CABAC(SyntaxElement *se, ImageParameters *img, DataPartiti
   int curr_len;
   DecodingEnvironmentPtr dep_dp = &(this_dataPart->de_cabac);
   curr_len = arideco_bits_read(dep_dp);
+
 #if (TRACE==2)
   fprintf(p_trace, "curr_len: %d\n",curr_len);
 #endif
+
   // perform the actual decoding by calling the appropriate method
   se->reading(se, img, dep_dp);
 //read again and minus curr_len = arideco_bits_read(dep_dp); from above
@@ -1633,27 +1559,22 @@ unsigned int unary_bin_max_decode(DecodingEnvironmentPtr dep_dp,
                                   int ctx_offset,
                                   unsigned int max_symbol)
 {
-  unsigned int l;
-  unsigned int symbol;
-  BiContextTypePtr ictx;
-
-  symbol =  biari_decode_symbol(dep_dp, ctx );
+  unsigned int symbol =  biari_decode_symbol(dep_dp, ctx );
 
-  if (symbol==0)
-    return 0;
-  else
-  {
-    if (max_symbol == 1)
+  if (symbol==0 || (max_symbol == 0))
     return symbol;
-    symbol=0;
-    ictx=ctx+ctx_offset;
+  else
+  {    
+    unsigned int l;
+    ctx += ctx_offset;
+    symbol = 0;
     do
     {
-      l=biari_decode_symbol(dep_dp, ictx);
+      l = biari_decode_symbol(dep_dp, ctx);
       symbol++;
     }
-    while( (l!=0) && (symbol<max_symbol-1) );
-    if ((l!=0) && (symbol==max_symbol-1))
+    while( (l != 0) && (symbol < max_symbol) );
+    if ((l != 0) && (symbol == max_symbol))
       symbol++;
     return symbol;
   }
@@ -1671,24 +1592,21 @@ unsigned int unary_bin_decode(DecodingEnvironmentPtr dep_dp,
                               BiContextTypePtr ctx,
                               int ctx_offset)
 {
-  unsigned int l;
-  unsigned int symbol;
-  BiContextTypePtr ictx;
-
-  symbol = biari_decode_symbol(dep_dp, ctx );
+  unsigned int symbol = biari_decode_symbol(dep_dp, ctx );
 
-  if (symbol==0)
+  if (symbol == 0)
     return 0;
   else
   {
-    symbol=0;
-    ictx=ctx+ctx_offset;
+    unsigned int l;
+    ctx += ctx_offset;;
+    symbol = 0;
     do
     {
-      l=biari_decode_symbol(dep_dp, ictx);
+      l=biari_decode_symbol(dep_dp, ctx);
       symbol++;
     }
-    while( l!=0 );
+    while( l != 0 );
     return symbol;
   }
 }
@@ -1705,19 +1623,16 @@ unsigned int unary_bin_decode(DecodingEnvironmentPtr dep_dp,
  * StW, 8.7.02
  ************************************************************************
  */
-int cabac_startcode_follows(ImageParameters *img, int eos_bit)
+int cabac_startcode_follows(Slice *currSlice, int eos_bit)
 {
-  Slice         *currSlice  = img->currentSlice;
-  int           *partMap    = assignSE2partition[currSlice->dp_mode];
-  DataPartition *dP;
-  unsigned int  bit;
-  DecodingEnvironmentPtr dep_dp;
-
-  dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);
-  dep_dp = &(dP->de_cabac);
+  static unsigned int  bit;
 
   if( eos_bit )
   {
+    int   *partMap    = assignSE2partition[currSlice->dp_mode];
+    DataPartition *dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);  
+    DecodingEnvironmentPtr dep_dp = &(dP->de_cabac);
+
     bit = biari_decode_final (dep_dp); //GB
 
 #if TRACE
@@ -1730,13 +1645,9 @@ int cabac_startcode_follows(ImageParameters *img, int eos_bit)
     bit = 0;
   }
 
-  return (bit==1?1:0);
+  return (bit == 1 ? 1 : 0);
 }
 
-
-
-
-
 /*!
  ************************************************************************
  * \brief
@@ -1753,8 +1664,8 @@ unsigned int exp_golomb_decode_eq_prob( DecodingEnvironmentPtr dep_dp,
 
   do
   {
-    l=biari_decode_symbol_eq_prob(dep_dp);
-    if (l==1)
+    l = biari_decode_symbol_eq_prob(dep_dp);
+    if (l == 1)
     {
       symbol += (1<<k);
       k++;
@@ -1766,7 +1677,7 @@ unsigned int exp_golomb_decode_eq_prob( DecodingEnvironmentPtr dep_dp,
     if (biari_decode_symbol_eq_prob(dep_dp)==1)
       binary_symbol |= (1<<k);
 
-  return (unsigned int) (symbol+binary_symbol);
+  return (unsigned int) (symbol + binary_symbol);
 }
 
 
@@ -1779,25 +1690,24 @@ unsigned int exp_golomb_decode_eq_prob( DecodingEnvironmentPtr dep_dp,
 unsigned int unary_exp_golomb_level_decode( DecodingEnvironmentPtr dep_dp,
                                             BiContextTypePtr ctx)
 {
-  unsigned int l,k;
-  unsigned int symbol;
-  unsigned int exp_start = 13;
-
-  symbol = biari_decode_symbol(dep_dp, ctx );
+  unsigned int symbol = biari_decode_symbol(dep_dp, ctx );
 
   if (symbol==0)
     return 0;
   else
   {
+    unsigned int l, k = 1;
+    unsigned int exp_start = 13;
+
     symbol=0;
-    k=1;
+
     do
     {
       l=biari_decode_symbol(dep_dp, ctx);
       symbol++;
       k++;
     }
-    while((l!=0) && (k!=exp_start));
+    while((l != 0) && (k != exp_start));
     if (l!=0)
       symbol += exp_golomb_decode_eq_prob(dep_dp,0)+1;
     return symbol;
@@ -1817,34 +1727,30 @@ unsigned int unary_exp_golomb_mv_decode(DecodingEnvironmentPtr dep_dp,
                                         BiContextTypePtr ctx,
                                         unsigned int max_bin)
 {
-  unsigned int l,k;
-  unsigned int bin=1;
-  unsigned int symbol;
-  unsigned int exp_start = 8;
-
-  BiContextTypePtr ictx=ctx;
+  unsigned int symbol = biari_decode_symbol(dep_dp, ctx );
 
-  symbol = biari_decode_symbol(dep_dp, ictx );
-
-  if (symbol==0)
+  if (symbol == 0)
     return 0;
   else
   {
+    unsigned int exp_start = 8;
+    unsigned int l,k = 1;
+    unsigned int bin = 1;
+
     symbol=0;
-    k=1;
 
-    ictx++;
+    ctx++;
     do
     {
-      l=biari_decode_symbol(dep_dp, ictx  );
-      if ((++bin)==2) ictx++;
-      if (bin==max_bin) ictx++;
+      l=biari_decode_symbol(dep_dp, ctx);
+      if ((++bin)==2) ctx++;
+      if (bin==max_bin) ctx++;
       symbol++;
       k++;
     }
     while((l!=0) && (k!=exp_start));
     if (l!=0)
-      symbol += exp_golomb_decode_eq_prob(dep_dp,3)+1;
+      symbol += exp_golomb_decode_eq_prob(dep_dp,3) + 1;
     return symbol;
   }
 }
diff --git a/ldecod/src/erc_do_p.c b/ldecod/src/erc_do_p.c
index c23dc07..38e25a1 100644
--- a/ldecod/src/erc_do_p.c
+++ b/ldecod/src/erc_do_p.c
@@ -595,7 +595,7 @@ static void buildPredRegionYUV(ImageParameters *img, int *mv, int x, int y, imgp
 
       for(ii=0;ii<BLOCK_SIZE;ii++)
         for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
-          img->mpr[LumaComp][jj+joff][ii+ioff]=tmp_block[jj][ii];
+          img->mb_pred[LumaComp][jj+joff][ii+ioff]=tmp_block[jj][ii];
     }
   }
 
@@ -604,7 +604,7 @@ static void buildPredRegionYUV(ImageParameters *img, int *mv, int x, int y, imgp
   {
     for (i = 0; i < 16; i++)
     {
-      pMB[j*16+i] = img->mpr[LumaComp][j][i];
+      pMB[j*16+i] = img->mb_pred[LumaComp][j][i];
     }
   }
   pMB += 256;
@@ -652,7 +652,7 @@ static void buildPredRegionYUV(ImageParameters *img, int *mv, int x, int y, imgp
               if0=f1_x-if1;
               jf0=f1_y-jf1;
 
-              img->mpr[uv + 1][jj+joff][ii+ioff]=(if0*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii0]+
+              img->mb_pred[uv + 1][jj+joff][ii+ioff]=(if0*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii0]+
                                           if1*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii1]+
                                           if0*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii0]+
                                           if1*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3;
@@ -665,7 +665,7 @@ static void buildPredRegionYUV(ImageParameters *img, int *mv, int x, int y, imgp
       {
         for (i = 0; i < 8; i++)
         {
-          pMB[j*8+i] = img->mpr[uv + 1][j][i];
+          pMB[j*8+i] = img->mb_pred[uv + 1][j][i];
         }
       }
       pMB += 64;
@@ -883,14 +883,14 @@ static void buildPredblockRegionYUV(ImageParameters *img, int *mv,
 
   for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
     for(ii=0;ii<BLOCK_SIZE;ii++)
-      img->mpr[LumaComp][jj][ii]=tmp_block[jj][ii];
+      img->mb_pred[LumaComp][jj][ii]=tmp_block[jj][ii];
 
 
   for (j = 0; j < 4; j++)
   {
     for (i = 0; i < 4; i++)
     {
-      pMB[j*4+i] = img->mpr[LumaComp][j][i];
+      pMB[j*4+i] = img->mb_pred[LumaComp][j][i];
     }
   }
   pMB += 16;
@@ -934,7 +934,7 @@ static void buildPredblockRegionYUV(ImageParameters *img, int *mv,
           if0=f1_x-if1;
           jf0=f1_y-jf1;
 
-          img->mpr[uv + 1][jj][ii]=(if0*jf0*listX[list][ref_frame]->imgUV[uv][jj0][ii0]+
+          img->mb_pred[uv + 1][jj][ii]=(if0*jf0*listX[list][ref_frame]->imgUV[uv][jj0][ii0]+
             if1*jf0*listX[list][ref_frame]->imgUV[uv][jj0][ii1]+
             if0*jf1*listX[list][ref_frame]->imgUV[uv][jj1][ii0]+
             if1*jf1*listX[list][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3;
@@ -945,7 +945,7 @@ static void buildPredblockRegionYUV(ImageParameters *img, int *mv,
       {
         for (i = 0; i < 2; i++)
         {
-          pMB[j*2+i] = img->mpr[uv + 1][j][i];
+          pMB[j*2+i] = img->mb_pred[uv + 1][j][i];
         }
       }
       pMB += 4;
@@ -1159,25 +1159,24 @@ static void copy_to_conceal(StorablePicture *src, StorablePicture *dst, ImagePar
 
     for(i=0;i<mb_height*4;i++)
     {
-      mm = i*BLOCK_SIZE;
+      mm = i * BLOCK_SIZE;
       for(j=0;j<mb_width*4;j++)
       {
-        nn = j*BLOCK_SIZE;
-
-        mv[0] = src->mv[LIST_0][i][j][0] / scale;
-        mv[1] = src->mv[LIST_0][i][j][1] / scale;
-        mv[2] = src->ref_idx[LIST_0][i][j];
+        nn = j * BLOCK_SIZE;
 
+        mv[0] = src->motion.mv[LIST_0][i][j][0] / scale;
+        mv[1] = src->motion.mv[LIST_0][i][j][1] / scale;
+        mv[2] = src->motion.ref_idx[LIST_0][i][j];
 
         if(mv[2]<0)
           mv[2]=0;
 
-        dst->mv[LIST_0][i][j][0] = mv[0];
-        dst->mv[LIST_0][i][j][1] = mv[1];
-        dst->ref_idx[LIST_0][i][j] = mv[2];
+        dst->motion.mv[LIST_0][i][j][0] = mv[0];
+        dst->motion.mv[LIST_0][i][j][1] = mv[1];
+        dst->motion.ref_idx[LIST_0][i][j] = mv[2];
 
-        x = (j)*multiplier;
-        y = (i)*multiplier;
+        x = (j) * multiplier;
+        y = (i) * multiplier;
 
         if ((mm%16==0) && (nn%16==0))
           img->current_mb_nr++;
diff --git a/ldecod/src/filehandle.c b/ldecod/src/filehandle.c
index 7a9c2ad..78d233d 100644
--- a/ldecod/src/filehandle.c
+++ b/ldecod/src/filehandle.c
@@ -37,6 +37,17 @@ void error(char *text, int code)
 
 static int bitcounter = 0;
 
+/*!
+************************************************************************
+* \brief
+*    decrement trace bitcounter (used for special case in mb aff)
+************************************************************************
+*/
+void dectracebitcnt(int count)
+{
+  bitcounter -= count;
+}
+
 /*!
  ************************************************************************
  * \brief
diff --git a/ldecod/src/header.c b/ldecod/src/header.c
index 7bde430..5e6a78d 100644
--- a/ldecod/src/header.c
+++ b/ldecod/src/header.c
@@ -243,22 +243,20 @@ int RestOfSliceHeader(void)
     img->model_number = 0;
   }
 
-  val = se_v("SH: slice_qp_delta", currStream);
+  currSlice->slice_qp_delta = val = se_v("SH: slice_qp_delta", currStream);
   currSlice->qp = img->qp = 26 + active_pps->pic_init_qp_minus26 + val;
+
   if ((img->qp < -img->bitdepth_luma_qp_scale) || (img->qp > 51))
     error ("slice_qp_delta makes slice_qp_y out of range", 500);
 
-
-  currSlice->slice_qp_delta = val;
-
   if(img->type==SP_SLICE || img->type == SI_SLICE)
   {
     if(img->type==SP_SLICE)
     {
       img->sp_switch = u_1 ("SH: sp_for_switch_flag", currStream);
     }
-    val = se_v("SH: slice_qs_delta", currStream);
-    img->qpsp = 26 + active_pps->pic_init_qs_minus26 + val;
+    currSlice->slice_qs_delta = val = se_v("SH: slice_qs_delta", currStream);
+    currSlice->qs = img->qpsp = 26 + active_pps->pic_init_qs_minus26 + val;    
     if ((img->qpsp < 0) || (img->qpsp > 51))
       error ("slice_qs_delta makes slice_qs_y out of range", 500);
   }
diff --git a/ldecod/src/image.c b/ldecod/src/image.c
index 76d1d2c..98b7cc5 100644
--- a/ldecod/src/image.c
+++ b/ldecod/src/image.c
@@ -44,6 +44,7 @@
 #include "output.h"
 #include "mb_access.h"
 #include "memalloc.h"
+#include "macroblock.h"
 
 #include "loopfilter.h"
 
@@ -51,6 +52,7 @@
 #include "context_ini.h"
 #include "cabac.h"
 #include "vlc.h"
+#include "quant.h"
 
 #include "errorconcealment.h"
 #include "erc_api.h"
@@ -74,28 +76,6 @@ StorablePicture *dec_picture_JV[MAX_PLANE];  //!< dec_picture to be used during
 
 OldSliceParams old_slice;
 
-void set_interpret_mb_mode(int slice_type)
-{
-  switch (slice_type)
-  {
-  case P_SLICE: case SP_SLICE:
-    interpret_mb_mode = interpret_mb_mode_P;
-    break;
-  case B_SLICE:
-    interpret_mb_mode = interpret_mb_mode_B;
-    break;
-  case I_SLICE: 
-    interpret_mb_mode = interpret_mb_mode_I;
-    break;
-  case SI_SLICE: 
-    interpret_mb_mode = interpret_mb_mode_SI;
-    break;
-  default:
-    printf("Unsupported slice type\n");
-    break;
-  }
-}
-
 void MbAffPostProc(void)
 {
   imgpel temp[32][16];
@@ -106,7 +86,7 @@ void MbAffPostProc(void)
   int i, y, x0, y0, uv;
   for (i=0; i<(int)dec_picture->PicSizeInMbs; i+=2)
   {
-    if (dec_picture->mb_field[i])
+    if (dec_picture->motion.mb_field[i])
     {
       get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
       for (y=0; y<(2*MB_BLOCK_SIZE);y++)
@@ -148,7 +128,7 @@ void MbAffPostProc(void)
  ***********************************************************************
  */
 
-int decode_one_frame(ImageParameters *img,struct inp_par *inp, struct snr_par *snr)
+int decode_one_frame(ImageParameters *img, struct inp_par *inp, struct snr_par *snr)
 {
   int current_header;
   Slice *currSlice = img->currentSlice;
@@ -359,7 +339,7 @@ void find_snr(
   int comp_size_x[3], comp_size_y[3];
   int64 framesize_in_bytes;
 
-  unsigned int max_pix_value_sqd[3] = {iabs2(img->max_imgpel_value),  iabs2(img->max_imgpel_value_uv), iabs2(img->max_imgpel_value_uv)};
+  unsigned int max_pix_value_sqd[3] = {iabs2(img->max_imgpel_value_comp[0]),  iabs2(img->max_imgpel_value_comp[1]), iabs2(img->max_imgpel_value_comp[2])};
 
   Boolean rgb_output = (Boolean) (active_sps->vui_seq_parameters.matrix_coefficients==0);
   unsigned char *buf;
@@ -447,22 +427,16 @@ void find_snr(
       }
     }
 
-#if ZEROSNR
-    diff_comp[k] = imax(diff_comp[k], 1);
-#endif
     // Collecting SNR statistics
-    if (diff_comp[k]  != 0)
-      snr->snr[k]=(float)(10*log10(max_pix_value_sqd[k]*(double)((double)(comp_size_x[k])*(comp_size_y[k]) / diff_comp[k])));   
-    else
-      snr->snr[k]=0.0;
+    snr->snr[k] = psnr( max_pix_value_sqd[k], comp_size_x[k] * comp_size_y[k], (float) diff_comp[k]);   
 
     if (img->number == 0) // first
     {
-      snr->snra[k]=snr->snr1[k]=snr->snr[k];                                                        // keep luma snr for first frame
+      snr->snra[k] = snr->snr[k];                                                        // keep luma snr for first frame
     }
     else
     {
-      snr->snra[k]=(float)(snr->snra[k]*(snr->frame_ctr)+snr->snr[k])/(snr->frame_ctr + 1); // average snr chroma for all frames
+      snr->snra[k] = (float)(snr->snra[k]*(snr->frame_ctr)+snr->snr[k])/(snr->frame_ctr + 1); // average snr chroma for all frames
     }
   }
 
@@ -471,14 +445,12 @@ void find_snr(
 
   free (buf);
 
-
   // picture error concealment
   if(p->concealed_pic)
   {
       fprintf(stdout,"%04d(P)  %8d %5d %5d %7.4f %7.4f %7.4f  %s %5d\n",
           frame_no, p->frame_poc, p->pic_num, p->qp,
           snr->snr[0], snr->snr[1], snr->snr[2], yuv_types[p->chroma_format_idc], 0);
-
   }
 }
 
@@ -579,50 +551,6 @@ void set_ref_pic_num(void)
   }
 }
 
-/*!
-************************************************************************
-* \brief
-*    Read the next NAL unit (with error handling)
-************************************************************************
-*/
-int read_next_nalu(NALU_t *nalu)
-{
-  int ret;
-
-  if (params->FileFormat == PAR_OF_ANNEXB)
-    ret = GetAnnexbNALU (nalu);
-  else
-    ret = GetRTPNALU (nalu);
-
-  if (ret < 0)
-  {
-    snprintf (errortext, ET_SIZE, "Error while getting the NALU in file format %s, exit\n", params->FileFormat==PAR_OF_ANNEXB?"Annex B":"RTP");
-    error (errortext, 601);
-  }
-  if (ret == 0)
-  {
-    FreeNALU(nalu);
-    return 0;
-  }
-
-  //In some cases, zero_byte shall be present. If current NALU is a VCL NALU, we can't tell
-  //whether it is the first VCL NALU at this point, so only non-VCL NAL unit is checked here.
-  CheckZeroByteNonVCL(nalu);
-
-  ret = NALUtoRBSP(nalu);
-
-  if (ret < 0)
-    error ("Invalid startcode emulation prevention found.", 602);
-
-
-  // Got a NALU
-  if (nalu->forbidden_bit)
-  {
-    error ("Found NALU with forbidden_bit set, bit error?", 603);
-  }
-
-  return nalu->len;
-}
 
 /*!
  ************************************************************************
@@ -641,12 +569,12 @@ int read_new_slice(void)
   int slice_id_a, slice_id_b, slice_id_c;
   int redundant_pic_cnt_b, redundant_pic_cnt_c;
   long ftell_position;
-
+  
   while (1)
   {
     ftell_position = ftell(bits);
 
-    if (0 == read_next_nalu(nalu))
+    if (0 == read_next_nalu(bits, nalu))
       return EOS;
 
     switch (nalu->nal_unit_type)
@@ -796,7 +724,7 @@ int read_new_slice(void)
         // continue with reading next DP
         ftell_position = ftell(bits);
 
-        if (0 == read_next_nalu(nalu))
+        if (0 == read_next_nalu(bits, nalu))
           return current_header;
         
         if ( NALU_TYPE_DPB == nalu->nal_unit_type)
@@ -829,7 +757,7 @@ int read_new_slice(void)
             // we're finished with DP_B, so let's continue with next DP
             ftell_position = ftell(bits);
 
-            if (0 == read_next_nalu(nalu))
+            if (0 == read_next_nalu(bits, nalu))
               return current_header;
           }
         }
@@ -927,7 +855,7 @@ int read_new_slice(void)
  */
 void init_picture(ImageParameters *img, struct inp_par *inp)
 {
-  int i,k,l;
+  int i,j,k,l;
   Slice *currSlice = img->currentSlice;
   int nplane;
 
@@ -943,8 +871,8 @@ void init_picture(ImageParameters *img, struct inp_par *inp)
     img->recovery_frame_num = img->frame_num;
 
   if (img->recovery_point == 0 &&
-      img->frame_num != img->pre_frame_num &&
-      img->frame_num != (img->pre_frame_num + 1) % img->MaxFrameNum)
+    img->frame_num != img->pre_frame_num &&
+    img->frame_num != (img->pre_frame_num + 1) % img->MaxFrameNum)
   {
     if (active_sps->gaps_in_frame_num_value_allowed_flag == 0)
     {
@@ -985,13 +913,13 @@ void init_picture(ImageParameters *img, struct inp_par *inp)
     img->pre_frame_num = img->frame_num;
   }
 
-  //img->num_dec_mb = 0;
+  img->num_dec_mb = 0;
 
   //calculate POC
   decode_poc(img);
 
   if (img->recovery_frame_num == img->frame_num &&
-      img->recovery_poc == 0x7fffffff)
+    img->recovery_poc == 0x7fffffff)
     img->recovery_poc = img->framepoc;
 
   if(img->nal_reference_idc)
@@ -1009,8 +937,8 @@ void init_picture(ImageParameters *img, struct inp_par *inp)
   dec_picture->top_poc=img->toppoc;
   dec_picture->bottom_poc=img->bottompoc;
   dec_picture->frame_poc=img->framepoc;
-  dec_picture->qp=img->qp;
-  dec_picture->slice_qp_delta=currSlice->slice_qp_delta;
+  dec_picture->qp = img->qp;
+  dec_picture->slice_qp_delta = currSlice->slice_qp_delta;
   dec_picture->chroma_qp_offset[0] = active_pps->chroma_qp_index_offset;
   dec_picture->chroma_qp_offset[1] = active_pps->second_chroma_qp_index_offset;
 
@@ -1052,10 +980,14 @@ void init_picture(ImageParameters *img, struct inp_par *inp)
   }
 
   // CAVLC init
-  for (i=0;i < (int)img->PicSizeInMbs; i++)
-    for (k=0;k<4;k++)
-      for (l=0;l<(4 + img->num_blk8x8_uv);l++)
-        img->nz_coeff[i][k][l]=-1;  // CAVLC
+  if (active_pps->entropy_coding_mode_flag == UVLC)
+  {
+    for (i=0;i < (int)img->PicSizeInMbs; i++)    
+      for (j = 0; j < 3; j++)
+        for (l = 0; l < 4; l++)
+          for (k = 0; k < 4;k++)
+            img->nz_coeff[i][j][l][k]=-1;  // CAVLC
+  }
 
   if(active_pps->constrained_intra_pred_flag)
   {
@@ -1173,7 +1105,7 @@ void exit_picture(void)
   unsigned int i;
   int structure, frame_poc, slice_type, refpic, qp, pic_num, chroma_format_idc, is_idr;
 
-  static char cslice_type[8];  
+  static char cslice_type[9];  
 
   time_t tmp_time;                   // time used by decoding the last frame
   char   yuvFormat[10];
@@ -1295,9 +1227,11 @@ void exit_picture(void)
       else if(refpic) // stored B pictures
         strcpy(cslice_type," B ");
       else // B pictures
-        strcpy(cslice_type," b ");    
+        strcpy(cslice_type," b ");
       if (structure==FRAME)
+      {
         strncat(cslice_type,")       ",8-strlen(cslice_type));
+      }
     }
     else if (structure==BOTTOM_FIELD)
     {
@@ -1395,18 +1329,18 @@ void ercWriteMBMODEandMV(Macroblock *currMB, ImageParameters *img,struct inp_par
         jj              = 4*mby + (i >> 1  )*2;
         if (currMB->b8mode[i]>=5 && currMB->b8mode[i]<=7)  // SMALL BLOCKS
         {
-          pRegion->mv[0]  = (dec_picture->mv[LIST_0][jj][ii][0] + dec_picture->mv[LIST_0][jj][ii+1][0] + dec_picture->mv[LIST_0][jj+1][ii][0] + dec_picture->mv[LIST_0][jj+1][ii+1][0] + 2)/4;
-          pRegion->mv[1]  = (dec_picture->mv[LIST_0][jj][ii][1] + dec_picture->mv[LIST_0][jj][ii+1][1] + dec_picture->mv[LIST_0][jj+1][ii][1] + dec_picture->mv[LIST_0][jj+1][ii+1][1] + 2)/4;
+          pRegion->mv[0]  = (dec_picture->motion.mv[LIST_0][jj][ii][0] + dec_picture->motion.mv[LIST_0][jj][ii+1][0] + dec_picture->motion.mv[LIST_0][jj+1][ii][0] + dec_picture->motion.mv[LIST_0][jj+1][ii+1][0] + 2)/4;
+          pRegion->mv[1]  = (dec_picture->motion.mv[LIST_0][jj][ii][1] + dec_picture->motion.mv[LIST_0][jj][ii+1][1] + dec_picture->motion.mv[LIST_0][jj+1][ii][1] + dec_picture->motion.mv[LIST_0][jj+1][ii+1][1] + 2)/4;
         }
         else // 16x16, 16x8, 8x16, 8x8
         {
-          pRegion->mv[0]  = dec_picture->mv[LIST_0][jj][ii][0];
-          pRegion->mv[1]  = dec_picture->mv[LIST_0][jj][ii][1];
-//          pRegion->mv[0]  = dec_picture->mv[LIST_0][4*mby+(i/2)*2][4*mbx+(i%2)*2+BLOCK_SIZE][0];
-//          pRegion->mv[1]  = dec_picture->mv[LIST_0][4*mby+(i/2)*2][4*mbx+(i%2)*2+BLOCK_SIZE][1];
+          pRegion->mv[0]  = dec_picture->motion.mv[LIST_0][jj][ii][0];
+          pRegion->mv[1]  = dec_picture->motion.mv[LIST_0][jj][ii][1];
+//          pRegion->mv[0]  = dec_picture->motion.mv[LIST_0][4*mby+(i/2)*2][4*mbx+(i%2)*2+BLOCK_SIZE][0];
+//          pRegion->mv[1]  = dec_picture->motion.mv[LIST_0][4*mby+(i/2)*2][4*mbx+(i%2)*2+BLOCK_SIZE][1];
         }
         erc_mvperMB      += iabs(pRegion->mv[0]) + iabs(pRegion->mv[1]);
-        pRegion->mv[2]    = dec_picture->ref_idx[LIST_0][jj][ii];
+        pRegion->mv[2]    = dec_picture->motion.ref_idx[LIST_0][jj][ii];
       }
     }
   }
@@ -1427,24 +1361,24 @@ void ercWriteMBMODEandMV(Macroblock *currMB, ImageParameters *img,struct inp_par
       }
       else
       {
-        int idx = (dec_picture->ref_idx[0][jj][ii]<0)?1:0;
+        int idx = (dec_picture->motion.ref_idx[0][jj][ii]<0)?1:0;
 //        int idx = (currMB->b8mode[i]==0 && currMB->b8pdir[i]==2 ? LIST_0 : currMB->b8pdir[i]==1 ? LIST_1 : LIST_0);
 //        int idx = currMB->b8pdir[i]==0 ? LIST_0 : LIST_1;
-        mv                = dec_picture->mv[idx];
+        mv                = dec_picture->motion.mv[idx];
         pRegion->mv[0]    = (mv[jj][ii][0] + mv[jj][ii+1][0] + mv[jj+1][ii][0] + mv[jj+1][ii+1][0] + 2)/4;
         pRegion->mv[1]    = (mv[jj][ii][1] + mv[jj][ii+1][1] + mv[jj+1][ii][1] + mv[jj+1][ii+1][1] + 2)/4;
         erc_mvperMB      += iabs(pRegion->mv[0]) + iabs(pRegion->mv[1]);
 
-        pRegion->mv[2]  = (dec_picture->ref_idx[idx][jj][ii]);
+        pRegion->mv[2]  = (dec_picture->motion.ref_idx[idx][jj][ii]);
 /*
         if (currMB->b8pdir[i]==0 || (currMB->b8pdir[i]==2 && currMB->b8mode[i]!=0)) // forward or bidirect
         {
-          pRegion->mv[2]  = (dec_picture->ref_idx[LIST_0][jj][ii]);
+          pRegion->mv[2]  = (dec_picture->motion.ref_idx[LIST_0][jj][ii]);
           ///???? is it right, not only "img->fw_refFrArr[jj][ii-4]"
         }
         else
         {
-          pRegion->mv[2]  = (dec_picture->ref_idx[LIST_1][jj][ii]);
+          pRegion->mv[2]  = (dec_picture->motion.ref_idx[LIST_1][jj][ii]);
 //          pRegion->mv[2]  = 0;
         }
         */
@@ -1613,12 +1547,12 @@ void decode_one_slice(ImageParameters *img,struct inp_par *inp)
 #endif
 
     // Initializes the current macroblock
-    start_macroblock(&currMB, img);
+    start_macroblock(img, &currMB);
     // Get the syntax elements from the NAL
-    read_one_macroblock(currMB, img);
-    decode_one_macroblock(currMB, img);
+    read_one_macroblock(img, currMB);
+    decode_one_macroblock(img, currMB, dec_picture);
 
-    if(img->MbaffFrameFlag && dec_picture->mb_field[img->current_mb_nr])
+    if(img->MbaffFrameFlag && dec_picture->motion.mb_field[img->current_mb_nr])
     {
       img->num_ref_idx_l0_active >>= 1;
       img->num_ref_idx_l1_active >>= 1;
diff --git a/ldecod/src/ldecod.c b/ldecod/src/ldecod.c
index 3dd36e4..3d0e542 100644
--- a/ldecod/src/ldecod.c
+++ b/ldecod/src/ldecod.c
@@ -15,7 +15,7 @@
  *     The main contributors are listed in contributors.h
  *
  *  \version
- *     JM 14.0 (FRExt)
+ *     JM 14.1 (FRExt)
  *
  *  \note
  *     tags are used for document system "doxygen"
@@ -58,9 +58,10 @@
 #include "parset.h"
 #include "sei.h"
 #include "erc_api.h"
+#include "quant.h"
 
 #define JM          "14 (FRExt)"
-#define VERSION     "14.0"
+#define VERSION     "14.1"
 #define EXT_VERSION "(FRExt)"
 
 #define LOGFILE     "log.dec"
@@ -341,7 +342,7 @@ int main(int argc, char **argv)
   img->dec_ref_pic_marking_buffer = NULL;
 
   // B pictures
-  Bframe_ctr=snr->frame_ctr=0;
+  Bframe_ctr = snr->frame_ctr = 0;
 
   // time for total decoding session
   tot_time = 0;
@@ -349,7 +350,7 @@ int main(int argc, char **argv)
   // reference flag initialization
   for(i=0;i<17;i++)
   {
-    ref_flag[i]=1;
+    ref_flag[i] = 1;
   }
 
   while (decode_one_frame(img, params, snr) != EOS)
@@ -434,14 +435,13 @@ void init(ImageParameters *img)  //!< image parameters
 void init_frext(ImageParameters *img)  //!< image parameters
 {
   //pel bitdepth init
-  img->bitdepth_luma_qp_scale   = 6*(img->bitdepth_luma   - 8);
+  img->bitdepth_luma_qp_scale   = 6 * (img->bitdepth_luma - 8);
   if(img->bitdepth_luma > img->bitdepth_chroma || active_sps->chroma_format_idc == YUV400)
     img->pic_unit_bitsize_on_disk = (img->bitdepth_luma > 8)? 16:8;
   else
     img->pic_unit_bitsize_on_disk = (img->bitdepth_chroma > 8)? 16:8;
-  img->dc_pred_value_comp[0] = 1<<(img->bitdepth_luma - 1);
-  img->max_imgpel_value = (1<<img->bitdepth_luma) - 1;
-  img->max_imgpel_value_comp[0] = img->max_imgpel_value;
+  img->dc_pred_value_comp[0]    = 1<<(img->bitdepth_luma - 1);
+  img->max_imgpel_value_comp[0] = (1<<img->bitdepth_luma) - 1;
   img->mb_size[0][0] = img->mb_size[0][1] = MB_BLOCK_SIZE;
 
   if (active_sps->chroma_format_idc != YUV400)
@@ -450,7 +450,8 @@ void init_frext(ImageParameters *img)  //!< image parameters
     img->bitdepth_chroma_qp_scale = 6 * (img->bitdepth_chroma - 8);
     img->dc_pred_value_comp[1]    = (1 << (img->bitdepth_chroma - 1));
     img->dc_pred_value_comp[2]    = img->dc_pred_value_comp[1];
-    img->max_imgpel_value_uv      = (1 << img->bitdepth_chroma) - 1;
+    img->max_imgpel_value_comp[1] = (1 << img->bitdepth_chroma) - 1;
+    img->max_imgpel_value_comp[2] = (1 << img->bitdepth_chroma) - 1;
     img->num_blk8x8_uv = (1 << active_sps->chroma_format_idc) & (~(0x1));
     img->num_uv_blocks = (img->num_blk8x8_uv >> 1);
     img->num_cdc_coeff = (img->num_blk8x8_uv << 1);
@@ -460,15 +461,14 @@ void init_frext(ImageParameters *img)  //!< image parameters
   else
   {
     img->bitdepth_chroma_qp_scale = 0;
-    img->max_imgpel_value_uv      = 0;
+    img->max_imgpel_value_comp[1] = 0;
+    img->max_imgpel_value_comp[2] = 0;
     img->num_blk8x8_uv = 0;
     img->num_uv_blocks = 0;
     img->num_cdc_coeff = 0;
     img->mb_size[1][0] = img->mb_size[2][0] = img->mb_cr_size_x  = 0;
     img->mb_size[1][1] = img->mb_size[2][1] = img->mb_cr_size_y  = 0;
   }
-  img->max_imgpel_value_comp[1] = img->max_imgpel_value_uv;
-  img->max_imgpel_value_comp[2] = img->max_imgpel_value_uv;
   img->mb_size_blk[0][0] = img->mb_size_blk[0][1] = img->mb_size[0][0] >> 2;
   img->mb_size_blk[1][0] = img->mb_size_blk[2][0] = img->mb_size[1][0] >> 2;
   img->mb_size_blk[1][1] = img->mb_size_blk[2][1] = img->mb_size[1][1] >> 2;
@@ -476,6 +476,8 @@ void init_frext(ImageParameters *img)  //!< image parameters
   img->mb_size_shift[0][0] = img->mb_size_shift[0][1] = CeilLog2_sf (img->mb_size[0][0]);
   img->mb_size_shift[1][0] = img->mb_size_shift[2][0] = CeilLog2_sf (img->mb_size[1][0]);
   img->mb_size_shift[1][1] = img->mb_size_shift[2][1] = CeilLog2_sf (img->mb_size[1][1]);
+
+  init_qp_process(img);
 }
 
 
@@ -967,7 +969,7 @@ int init_global_buffers(void)
   memory_size += get_mem4Dint(&(img->wbp_weight), 6, MAX_REFERENCE_PICTURES, MAX_REFERENCE_PICTURES, 3);
 
   // CAVLC mem
-  memory_size += get_mem3Dint(&(img->nz_coeff), img->FrameSizeInMbs, 4, 4 + img->num_blk8x8_uv);
+  memory_size += get_mem4Dint(&(img->nz_coeff), img->FrameSizeInMbs, 3, BLOCK_SIZE, BLOCK_SIZE);
 
   memory_size += get_mem2Dint(&(img->siblock), img->FrameHeightInMbs, img->PicWidthInMbs);
 
@@ -1000,7 +1002,7 @@ void free_global_buffers(void)
     free_mem3Dpel (imgUV_ref);
 
   // CAVLC free mem
-  free_mem3Dint(img->nz_coeff);
+  free_mem4Dint(img->nz_coeff);
 
   free_mem2Dint(img->siblock);
 
diff --git a/ldecod/src/loopFilter.c b/ldecod/src/loopFilter.c
index e330ae8..de06920 100644
--- a/ldecod/src/loopFilter.c
+++ b/ldecod/src/loopFilter.c
@@ -285,12 +285,12 @@ void GetStrengthNormal(byte Strength[MB_BLOCK_SIZE], ImageParameters *img, int M
 
     if (!ANY_INTRA)
     {
-      list0_refPicIdArr = p->ref_pic_id[LIST_0];
-      list1_refPicIdArr = p->ref_pic_id[LIST_1];
-      list0_mv = p->mv[LIST_0];
-      list1_mv = p->mv[LIST_1];
-      list0_refIdxArr = p->ref_idx[LIST_0];
-      list1_refIdxArr = p->ref_idx[LIST_1];
+      list0_refPicIdArr = p->motion.ref_pic_id[LIST_0];
+      list1_refPicIdArr = p->motion.ref_pic_id[LIST_1];
+      list0_mv = p->motion.mv[LIST_0];
+      list1_mv = p->motion.mv[LIST_1];
+      list0_refIdxArr = p->motion.ref_idx[LIST_0];
+      list1_refIdxArr = p->motion.ref_idx[LIST_1];
 
       get_mb_block_pos (MbQAddr, &mb_x, &mb_y);
       mb_x <<= 2;
@@ -420,12 +420,12 @@ void GetStrengthMBAff(byte Strength[16], ImageParameters *img, int MbQAddr, int
   int dir_m1 = (1 - dir);
 
   MbQ = &(img->mb_data[MbQAddr]);
-  list0_mv = p->mv[LIST_0];
-  list1_mv = p->mv[LIST_1];
-  list0_refIdxArr = p->ref_idx[LIST_0];
-  list1_refIdxArr = p->ref_idx[LIST_1];
-  list0_refPicIdArr = p->ref_pic_id[LIST_0];
-  list1_refPicIdArr = p->ref_pic_id[LIST_1];
+  list0_mv = p->motion.mv[LIST_0];
+  list1_mv = p->motion.mv[LIST_1];
+  list0_refIdxArr = p->motion.ref_idx[LIST_0];
+  list1_refIdxArr = p->motion.ref_idx[LIST_1];
+  list0_refPicIdArr = p->motion.ref_pic_id[LIST_0];
+  list1_refPicIdArr = p->motion.ref_pic_id[LIST_1];
 
   for( idx=0 ; idx<16 ; idx++ )
   {
@@ -821,7 +821,7 @@ void EdgeLoopChromaNormal(imgpel** Img, byte Strength[16],ImageParameters *img,
   static int      QP;
   
   int      bitdepth_scale = img->bitdepth_scale[IS_CHROMA];
-  int      max_imgpel_value_uv = img->max_imgpel_value_uv;
+  int      max_imgpel_value = img->max_imgpel_value_comp[uv + 1];
 
   int xQ = dir ? 0 : edge - 1;
   int yQ = dir ? (edge < 16 ? edge - 1: 0) : 0;
@@ -893,8 +893,8 @@ void EdgeLoopChromaNormal(imgpel** Img, byte Strength[16],ImageParameters *img,
             tc0  = ClipTab[ Strng ] * bitdepth_scale + 1;
             dif = iClip3( -tc0, tc0, ( ((R0 - L0) << 2) + (L1 - R1) + 4) >> 3 );
 
-            *SrcPtrP = (imgpel) iClip1 ( max_imgpel_value_uv, L0 + dif) ;
-            *SrcPtrQ = (imgpel) iClip1 ( max_imgpel_value_uv, R0 - dif) ;
+            *SrcPtrP = (imgpel) iClip1 ( max_imgpel_value, L0 + dif) ;
+            *SrcPtrQ = (imgpel) iClip1 ( max_imgpel_value, R0 - dif) ;
           }
         }
       }
@@ -926,6 +926,7 @@ void EdgeLoopChromaMBAff(imgpel** Img, byte Strength[16],ImageParameters *img, i
   PixelPos pixP, pixQ;
   int      dir_m1 = 1 - dir;
   int      bitdepth_scale = img->bitdepth_scale[IS_CHROMA];
+  int      max_imgpel_value = img->max_imgpel_value_comp[uv + 1];
 
   MbQ = &(img->mb_data[MbQAddr]);
   for( pel = 0 ; pel < PelNum ; pel++ )
@@ -977,8 +978,8 @@ void EdgeLoopChromaMBAff(imgpel** Img, byte Strength[16],ImageParameters *img, i
               tc0  = (C0 + 1);
               dif = iClip3( -tc0, tc0, ( ((R0 - L0) << 2) + (L1 - R1) + 4) >> 3 );
 
-              SrcPtrP[0] = (imgpel) iClip1 ( img->max_imgpel_value_uv, L0 + dif );
-              SrcPtrQ[0] = (imgpel) iClip1 ( img->max_imgpel_value_uv, R0 - dif );
+              SrcPtrP[0] = (imgpel) iClip1 ( max_imgpel_value, L0 + dif );
+              SrcPtrQ[0] = (imgpel) iClip1 ( max_imgpel_value, R0 - dif );
             }
           }
         }
diff --git a/ldecod/src/macroblock.c b/ldecod/src/macroblock.c
index f3b0a26..31c8838 100644
--- a/ldecod/src/macroblock.c
+++ b/ldecod/src/macroblock.c
@@ -17,6 +17,7 @@
  *    - Gabi Blaettermann
  *    - Ye-Kui Wang                     <wyk@ieee.org>
  *    - Lowell Winger                   <lwinger@lsil.com>
+ *    - Alexis Michael Tourapis         <alexismt@ieee.org>
  ***********************************************************************
 */
 
@@ -39,17 +40,223 @@
 #include "transform8x8.h"
 #include "transform.h"
 #include "mc_prediction.h"
+#include "quant.h"
 
 #if TRACE
 #define TRACE_STRING(s) strncpy(currSE.tracestring, s, TRACESTRING_SIZE)
+#define TRACE_DECBITS(i) dectracebitcnt(1)
+#define TRACE_PRINTF(s) sprintf(type, "%s", s);
+#define TRACE_STRING_P(s) strncpy(currSE->tracestring, s, TRACESTRING_SIZE)
 #else
-#define TRACE_STRING(s) // do nothing
+#define TRACE_STRING(s)
+#define TRACE_DECBITS(i)
+#define TRACE_PRINTF(s) 
+#define TRACE_STRING_P(s)
 #endif
 
+//! single scan pattern
+static const byte SNGL_SCAN[16][2] =
+{
+  {0,0},{1,0},{0,1},{0,2},
+  {1,1},{2,0},{3,0},{2,1},
+  {1,2},{0,3},{1,3},{2,2},
+  {3,1},{3,2},{2,3},{3,3}
+};
+
+//! field scan pattern
+static const byte FIELD_SCAN[16][2] =
+{
+  {0,0},{0,1},{1,0},{0,2},
+  {0,3},{1,1},{1,2},{1,3},
+  {2,0},{2,1},{2,2},{2,3},
+  {3,0},{3,1},{3,2},{3,3}
+};
+
+//! used to control block sizes : Not used/16x16/16x8/8x16/8x8/8x4/4x8/4x4
+static const int BLOCK_STEP[8][2]=
+{
+  {0,0},{4,4},{4,2},{2,4},{2,2},{2,1},{1,2},{1,1}
+};
+
+const byte QP_SCALE_CR[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
+
+};
+
+//! single scan pattern
+const byte SNGL_SCAN8x8[64][2] = {
+  {0,0}, {1,0}, {0,1}, {0,2}, {1,1}, {2,0}, {3,0}, {2,1}, {1,2}, {0,3}, {0,4}, {1,3}, {2,2}, {3,1}, {4,0}, {5,0},
+  {4,1}, {3,2}, {2,3}, {1,4}, {0,5}, {0,6}, {1,5}, {2,4}, {3,3}, {4,2}, {5,1}, {6,0}, {7,0}, {6,1}, {5,2}, {4,3},
+  {3,4}, {2,5}, {1,6}, {0,7}, {1,7}, {2,6}, {3,5}, {4,4}, {5,3}, {6,2}, {7,1}, {7,2}, {6,3}, {5,4}, {4,5}, {3,6},
+  {2,7}, {3,7}, {4,6}, {5,5}, {6,4}, {7,3}, {7,4}, {6,5}, {5,6}, {4,7}, {5,7}, {6,6}, {7,5}, {7,6}, {6,7}, {7,7}
+};
+
+
+//! field scan pattern
+const byte FIELD_SCAN8x8[64][2] = {   // 8x8
+  {0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {0,3}, {0,4}, {1,2}, {2,0}, {1,3}, {0,5}, {0,6}, {0,7}, {1,4}, {2,1}, {3,0},
+  {2,2}, {1,5}, {1,6}, {1,7}, {2,3}, {3,1}, {4,0}, {3,2}, {2,4}, {2,5}, {2,6}, {2,7}, {3,3}, {4,1}, {5,0}, {4,2},
+  {3,4}, {3,5}, {3,6}, {3,7}, {4,3}, {5,1}, {6,0}, {5,2}, {4,4}, {4,5}, {4,6}, {4,7}, {5,3}, {6,1}, {6,2}, {5,4},
+  {5,5}, {5,6}, {5,7}, {6,3}, {7,0}, {7,1}, {6,4}, {6,5}, {6,6}, {6,7}, {7,2}, {7,3}, {7,4}, {7,5}, {7,6}, {7,7}
+};
+
+//! single scan pattern
+const byte SCAN_YUV422[8][2] =
+{
+  {0,0},{0,1},
+  {1,0},{0,2},
+  {0,3},{1,1},
+  {1,2},{1,3}
+};
+
+static unsigned char cbp_blk_chroma[8][4] =
+{ {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} };
+
+//! look up tables for FRExt_chroma support
+const unsigned char subblk_offset_x[3][8][4] =
+{
+  { {0, 4, 0, 4},
+    {0, 4, 0, 4},
+    {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, 4, 0, 4},
+    {0, 4, 0, 4},
+    {0, 4, 0, 4},
+    {0, 4, 0, 4},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}, },
+
+  { {0, 4, 0, 4},
+    {8,12, 8,12},
+    {0, 4, 0, 4},
+    {8,12, 8,12},
+    {0, 4, 0, 4},
+    {8,12, 8,12},
+    {0, 4, 0, 4},
+    {8,12, 8,12}  }
+};
+
+const unsigned char subblk_offset_y[3][8][4] =
+{ { {0, 0, 4, 4},
+    {0, 0, 4, 4},
+    {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, 4, 4},
+    {8, 8,12,12},
+    {0, 0, 4, 4},
+    {8, 8,12,12},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}  },
+
+  { {0, 0, 4, 4},
+    {0, 0, 4, 4},
+    {8, 8,12,12},
+    {8, 8,12,12},
+    {0, 0, 4, 4},
+    {0, 0, 4, 4},
+    {8, 8,12,12},
+    {8, 8,12,12} }
+};
+
+const unsigned char cofuv_blk_x[3][8][4] =
+{ { {0, 1, 0, 1},
+    {0, 1, 0, 1},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0} },
+
+  { {0, 1, 0, 1},
+    {0, 1, 0, 1},
+    {0, 1, 0, 1},
+    {0, 1, 0, 1},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0} },
+
+  { {0, 1, 0, 1},
+    {2, 3, 2, 3},
+    {0, 1, 0, 1},
+    {2, 3, 2, 3},
+    {0, 1, 0, 1},
+    {2, 3, 2, 3},
+    {0, 1, 0, 1},
+    {2, 3, 2, 3} }
+};
+
+static const unsigned char cofuv_blk_y[3][8][4] =
+{
+  { { 0, 0, 1, 1},
+    { 0, 0, 1, 1},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0} },
+
+  { { 0, 0, 1, 1},
+    { 2, 2, 3, 3},
+    { 0, 0, 1, 1},
+    { 2, 2, 3, 3},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 0} },
+
+  { { 0, 0, 1, 1},
+    { 0, 0, 1, 1},
+    { 2, 2, 3, 3},
+    { 2, 2, 3, 3},
+    { 0, 0, 1, 1},
+    { 0, 0, 1, 1},
+    { 2, 2, 3, 3},
+    { 2, 2, 3, 3}}
+};
+
+void dectracebitcnt(int count);
+
 extern int last_dquant;
 extern ColocatedParams *Co_located;
 extern ColocatedParams *Co_located_JV[MAX_PLANE];  //!< Co_located to be used during 4:4:4 independent mode decoding
 
+
+static void readMotionInfoFromNAL  (ImageParameters *img, Macroblock *currMB);
+static void read_ipred_modes       (ImageParameters *img, Macroblock *currMB);
+static void readCBPandCoeffsFromNAL(ImageParameters *img, Macroblock *currMB);
+static void readIPCMcoeffsFromNAL  (ImageParameters *img, struct datapartition *dP);
+
+// Interpret MB mode
+static void (*interpret_mb_mode)(Macroblock *currMB);
+
 /*!
  ************************************************************************
  * \brief
@@ -152,6 +359,55 @@ static inline void prepareListforRefIdx ( SyntaxElement *currSE, DataPartition *
   }    
 }
 
+void set_chroma_qp(ImageParameters *img, Macroblock* currMB)
+{
+  int i;
+  for (i=0; i<2; i++)
+  {
+    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + dec_picture->chroma_qp_offset[i] );
+    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
+    currMB->qp_scaled[i + 1] = currMB->qpc[i] + img->bitdepth_chroma_qp_scale;
+  }
+}
+
+/*!
+************************************************************************
+* \brief
+*    updates chroma QP according to luma QP and bit depth
+************************************************************************
+*/
+void update_qp(ImageParameters *img, Macroblock *currMB, int qp)
+{
+  currMB->qp = qp;
+  currMB->qp_scaled[0] = qp + img->bitdepth_luma_qp_scale;
+  set_chroma_qp(img, currMB);
+}
+
+static void read_delta_quant(SyntaxElement *currSE, DataPartition *dP, Slice *currSlice, ImageParameters *img, Macroblock *currMB, int *partMap, int type)
+{
+  currSE->type = type;
+
+  dP = &(currSlice->partArr[partMap[currSE->type]]);
+
+  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
+  {
+    currSE->mapping = linfo_se;
+  }
+  else
+    currSE->reading= readDquant_CABAC;
+
+  TRACE_STRING_P("mb_qp_delta");
+
+  dP->readSyntaxElement(currSE,img,dP);
+  currMB->delta_quant = currSE->value1;
+  if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2)))
+    error ("mb_qp_delta is out of range", 500);
+
+  img->qp = ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) -
+    img->bitdepth_luma_qp_scale;
+  update_qp(img, currMB, img->qp);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -204,7 +460,7 @@ static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP
       kk = 2 * (j0 >> 1) + (i0 >> 1);
       if ((currMB->b8pdir[kk]== list || currMB->b8pdir[kk]== BI_PRED) && (currMB->b8mode[kk] !=0))//has forward vector
       {
-        cur_ref_idx = dec_picture->ref_idx[list][img->block_y+j0][img->block_x+i0];
+        cur_ref_idx = dec_picture->motion.ref_idx[list][img->block_y+j0][img->block_x+i0];
         mv_mode  = currMB->b8mode[kk];
         step_h = BLOCK_STEP [mv_mode][0];
         step_v = BLOCK_STEP [mv_mode][1];
@@ -213,7 +469,7 @@ static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP
         {
           img->subblock_y = j; // position used for context determination
           j4 = img->block_y + j;
-          mv  = &dec_picture->mv [list][j4];
+          mv  = &dec_picture->motion.mv [list][j4];
           mvd = &currMB->mvd     [list][j];
           for (i = i0; i < i0 + step_h0; i += step_h)
           {
@@ -221,7 +477,7 @@ static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP
             i4 = img->block_x + i;
 
             // first make mv-prediction
-            SetMotionVectorPredictor (currMB, img, pred_mv, cur_ref_idx, (byte) list, dec_picture->ref_idx, dec_picture->mv, BLOCK_SIZE * i, BLOCK_SIZE * j, 4*step_h, 4*step_v);
+            SetMotionVectorPredictor (img, currMB, pred_mv, cur_ref_idx, (byte) list, dec_picture->motion.ref_idx, dec_picture->motion.mv, BLOCK_SIZE * i, BLOCK_SIZE * j, 4*step_h, 4*step_v);
 
             for (k=0; k < 2; k++)
             {
@@ -265,7 +521,7 @@ static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP
   }
 }
 
-void invScaleCoeff(Macroblock *currMB, ImageParameters *img, int level, int run, int qp_per, int i, int j, int i0, int j0, int coef_ctr, const byte (*pos_scan4x4)[2], int (*InvLevelScale4x4)[4])
+void invScaleCoeff(ImageParameters *img, Macroblock *currMB, int level, int run, int qp_per, int i, int j, int i0, int j0, int coef_ctr, const byte (*pos_scan4x4)[2], int (*InvLevelScale4x4)[4])
 {
   if (level != 0)    /* leave if len=1 */
   {
@@ -285,7 +541,7 @@ void invScaleCoeff(Macroblock *currMB, ImageParameters *img, int level, int run,
  *    initializes the current macroblock
  ************************************************************************
  */
-void start_macroblock(Macroblock **currMB, ImageParameters *img)
+void start_macroblock(ImageParameters *img, Macroblock **currMB)
 {
   int mb_nr = img->current_mb_nr;
   *currMB = &img->mb_data[mb_nr];   // intialization code deleted, see below, StW  
@@ -296,8 +552,8 @@ void start_macroblock(Macroblock **currMB, ImageParameters *img)
   /* Update coordinates of the current macroblock */
   if (img->MbaffFrameFlag)
   {
-    img->mb_x = (mb_nr)%((2*img->width)/MB_BLOCK_SIZE);
-    img->mb_y = 2*((mb_nr)/((2*img->width)/MB_BLOCK_SIZE));
+    img->mb_x =    (mb_nr) % ((2*img->width) / MB_BLOCK_SIZE);
+    img->mb_y = 2*((mb_nr) / ((2*img->width) / MB_BLOCK_SIZE));
 
     img->mb_y += (img->mb_x & 0x01);
     img->mb_x >>= 1;
@@ -348,14 +604,13 @@ void start_macroblock(Macroblock **currMB, ImageParameters *img)
   memset((*currMB)->cbp_bits, 0, 3 * sizeof(int64));
   memset((*currMB)->cbp_bits_8x8, 0, 3 * sizeof(int64));
 
-  // initialize img->m7
-  memset(&(img->m7[0][0][0]), 0, 3 * MB_PIXELS * sizeof(int));
+  // initialize img->mb_rres
+  memset(&(img->mb_rres[0][0][0]), 0, 3 * MB_PIXELS * sizeof(int));
 
   // store filtering parameters for this MB
   (*currMB)->DFDisableIdc = img->currentSlice->DFDisableIdc;
   (*currMB)->DFAlphaC0Offset = img->currentSlice->DFAlphaC0Offset;
   (*currMB)->DFBetaOffset = img->currentSlice->DFBetaOffset;
-
 }
 
 /*!
@@ -387,16 +642,16 @@ Boolean exit_macroblock(ImageParameters *img,int eos_bit)
 
     if (img->current_mb_nr == -1)     // End of Slice group, MUST be end of slice
     {
-      assert (nal_startcode_follows (img, eos_bit) == TRUE);
+      assert (nal_startcode_follows (img->currentSlice, eos_bit) == TRUE);
       return TRUE;
     }
 
-    if(nal_startcode_follows(img, eos_bit) == FALSE)
+    if(nal_startcode_follows(img->currentSlice, eos_bit) == FALSE)
       return FALSE;
 
     if(img->type == I_SLICE  || img->type == SI_SLICE || active_pps->entropy_coding_mode_flag == CABAC)
       return TRUE;
-    if(img->cod_counter<=0)
+    if(img->cod_counter <= 0)
       return TRUE;
     return FALSE;
   }
@@ -408,7 +663,7 @@ Boolean exit_macroblock(ImageParameters *img,int eos_bit)
  *    Interpret the mb mode for P-Frames
  ************************************************************************
  */
-void interpret_mb_mode_P(Macroblock *currMB)
+static void interpret_mb_mode_P(Macroblock *currMB)
 {
   const int ICBPTAB[6] = {0,16,32,15,31,47};
   int         mbmode = currMB->mb_type;
@@ -461,7 +716,7 @@ void interpret_mb_mode_P(Macroblock *currMB)
  *    Interpret the mb mode for I-Frames
  ************************************************************************
  */
-void interpret_mb_mode_I(Macroblock *currMB)
+static void interpret_mb_mode_I(Macroblock *currMB)
 {
   static const int ICBPTAB[6] = {0,16,32,15,31,47};
   int         mbmode   = currMB->mb_type;
@@ -497,7 +752,7 @@ void interpret_mb_mode_I(Macroblock *currMB)
  *    Interpret the mb mode for B-Frames
  ************************************************************************
  */
-void interpret_mb_mode_B(Macroblock *currMB)
+static void interpret_mb_mode_B(Macroblock *currMB)
 {
   static const int offset2pdir16x16[12]   = {0, 0, 1, 2, 0,0,0,0,0,0,0,0};
   static const int offset2pdir16x8[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},{1,0},
@@ -578,7 +833,7 @@ void interpret_mb_mode_B(Macroblock *currMB)
  *    Interpret the mb mode for SI-Frames
  ************************************************************************
  */
-void interpret_mb_mode_SI(Macroblock *currMB)
+static void interpret_mb_mode_SI(Macroblock *currMB)
 {
   const int ICBPTAB[6] = {0,16,32,15,31,47};
   int         mbmode   = currMB->mb_type;
@@ -614,13 +869,41 @@ void interpret_mb_mode_SI(Macroblock *currMB)
     memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
   }
 }
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Set mode interpretation based on slice type
+ ************************************************************************
+ */
+void set_interpret_mb_mode(int slice_type)
+{
+  switch (slice_type)
+  {
+  case P_SLICE: case SP_SLICE:
+    interpret_mb_mode = interpret_mb_mode_P;
+    break;
+  case B_SLICE:
+    interpret_mb_mode = interpret_mb_mode_B;
+    break;
+  case I_SLICE: 
+    interpret_mb_mode = interpret_mb_mode_I;
+    break;
+  case SI_SLICE: 
+    interpret_mb_mode = interpret_mb_mode_SI;
+    break;
+  default:
+    printf("Unsupported slice type\n");
+    break;
+  }
+}
 /*!
  ************************************************************************
  * \brief
  *    init macroblock I and P frames
  ************************************************************************
  */
-void init_macroblock(ImageParameters *img)
+static void init_macroblock(ImageParameters *img)
 {
   int i, j, k;
 
@@ -628,13 +911,14 @@ void init_macroblock(ImageParameters *img)
   {
     for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
       memset(&img->ipredmode[j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(char));
+
     for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
     {                           // reset vectors and pred. modes
-      memset(&dec_picture->mv[k][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
-      memset(&dec_picture->ref_idx[k][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
-      for (i=img->block_x;i<img->block_x+BLOCK_SIZE;i++)
+      memset(&dec_picture->motion.mv[k][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
+      memset(&dec_picture->motion.ref_idx[k][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
+      for (i = img->block_x; i < img->block_x + BLOCK_SIZE;i++)
       {
-        dec_picture->ref_pic_id[k][j][i] = INT64_MIN;
+        dec_picture->motion.ref_pic_id[k][j][i] = INT64_MIN;
       }
     }
   }
@@ -658,29 +942,28 @@ void SetB8Mode (ImageParameters* img, Macroblock* currMB, int value, int i)
   {
     currMB->b8mode[i] = (char) b_v2b8[value];
     currMB->b8pdir[i] = (char) b_v2pd[value];
-
   }
   else
   {
     currMB->b8mode[i] = (char) p_v2b8[value];
     currMB->b8pdir[i] = (char) p_v2pd[value];
   }
-
 }
 
 
 void reset_coeffs(void)
 {
   // reset all coeffs
+  memset(&img->fcf[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));
   memset(&img->cof[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));
-  
+
   // CAVLC
-  memset(&img->nz_coeff[img->current_mb_nr][0][0],0, BLOCK_SIZE * (BLOCK_SIZE + img->num_blk8x8_uv) * sizeof(int));
+  if (active_pps->entropy_coding_mode_flag == UVLC)
+    memset(&img->nz_coeff[img->current_mb_nr][0][0][0], 0, 3 * BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
 }
 
 void field_flag_inference(Macroblock *currMB)
 {
-
   if (currMB->mbAvailA)
   {
     currMB->mb_field = img->mb_data[currMB->mbAddrA].mb_field;
@@ -692,16 +975,91 @@ void field_flag_inference(Macroblock *currMB)
   }
 }
 
-void set_chroma_qp(Macroblock* currMB)
+
+void copy_macroblock(ImageParameters *img, Macroblock *currMB)
 {
-  int i;
-  for (i=0; i<2; i++)
+  short pred_mv[2];
+  int zeroMotionAbove;
+  int zeroMotionLeft;
+  PixelPos mb_a, mb_b;
+  int   i, j;
+  int   a_mv_y = 0;
+  int   a_ref_idx = 0;
+  int   b_mv_y = 0;
+  int   b_ref_idx = 0;
+  int   img_block_y   = img->block_y;
+  int   list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
+  short ***cur_mv = dec_picture->motion.mv[LIST_0];
+  get4x4Neighbour(currMB,-1, 0, img->mb_size[IS_LUMA], &mb_a);
+  get4x4Neighbour(currMB, 0,-1, img->mb_size[IS_LUMA], &mb_b);
+
+  if (mb_a.available)
   {
-    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + dec_picture->chroma_qp_offset[i] );
-    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
+    a_mv_y    = cur_mv[mb_a.pos_y][mb_a.pos_x][1];
+    a_ref_idx = dec_picture->motion.ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];
+
+    if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
+    {
+      a_mv_y    /=2;
+      a_ref_idx *=2;
+    }
+    if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field)
+    {
+      a_mv_y    *=2;
+      a_ref_idx >>=1;
+    }
   }
-}
 
+  if (mb_b.available)
+  {
+    b_mv_y    = cur_mv[mb_b.pos_y][mb_b.pos_x][1];
+    b_ref_idx = dec_picture->motion.ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];
+
+    if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
+    {
+      b_mv_y    /=2;
+      b_ref_idx *=2;
+    }
+    if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field)
+    {
+      b_mv_y    *=2;
+      b_ref_idx >>=1;
+    }
+  }
+
+  zeroMotionLeft  = !mb_a.available ? 1 : a_ref_idx==0 && cur_mv[mb_a.pos_y][mb_a.pos_x][0]==0 && a_mv_y==0 ? 1 : 0;
+  zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && cur_mv[mb_b.pos_y][mb_b.pos_x][0]==0 && b_mv_y==0 ? 1 : 0;
+
+  currMB->cbp = 0;
+  reset_coeffs();
+
+  if (zeroMotionAbove || zeroMotionLeft)
+  {
+    for(j = img_block_y; j < img_block_y + BLOCK_SIZE;j++)
+    {
+      memset(&cur_mv[j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
+    }
+  }
+  else
+  {
+    SetMotionVectorPredictor (img, currMB, pred_mv, 0, LIST_0, dec_picture->motion.ref_idx, dec_picture->motion.mv, 0, 0, 16, 16);
+
+    for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++)
+    {        
+      for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
+        memcpy(&cur_mv[j][i][0], &pred_mv[0], 2 * sizeof(short));
+    }
+  }
+  for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++)
+  {
+    memset(&dec_picture->motion.ref_idx[LIST_0][j][img->block_x], 0, BLOCK_SIZE * sizeof(char));
+    for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
+    {        
+      dec_picture->motion.ref_pic_id[LIST_0][j][i] =
+        dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j][i]];
+    }
+  }  
+}
 
 /*!
  ************************************************************************
@@ -709,9 +1067,9 @@ void set_chroma_qp(Macroblock* currMB)
  *    Get the syntax elements from the NAL
  ************************************************************************
  */
-void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
+void read_one_macroblock(ImageParameters *img, Macroblock *currMB)
 {
-  int i, j;
+  int i;
 
   SyntaxElement currSE;
   int mb_nr = img->current_mb_nr; 
@@ -721,7 +1079,6 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
   int *partMap = assignSE2partition[currSlice->dp_mode];
   Macroblock *topMB = NULL;
   int  prevMbSkipped = 0;
-  int  img_block_y;
   int  check_bottom, read_bottom, read_top;  
 
   if (img->MbaffFrameFlag)
@@ -740,19 +1097,15 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
 
   currMB->mb_field = ((mb_nr&0x01) == 0)? 0 : img->mb_data[mb_nr-1].mb_field;
 
-  currMB->qp = img->qp ;
-  for (i=0; i<2; i++)
-  {
-    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, img->qp + dec_picture->chroma_qp_offset[i] );
-    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
-  }
+  update_qp(img, currMB, img->qp);
 
   currSE.type = SE_MBTYPE;
 
   //  read MB mode *****************************************************************
   dP = &(currSlice->partArr[partMap[currSE.type]]);
 
-  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   currSE.mapping = linfo_ue;
+  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   
+    currSE.mapping = linfo_ue;
 
   if(img->type == I_SLICE || img->type == SI_SLICE)
   {
@@ -772,6 +1125,7 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
       }
       currMB->mb_field = currSE.value1;
     }
+    
     if(active_pps->entropy_coding_mode_flag  == CABAC)
       CheckAvailabilityOfNeighborsCABAC(currMB);
 
@@ -802,7 +1156,7 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
     if (img->type==B_SLICE)
       currMB->cbp = currSE.value2;
 
-    if(!dP->bitstream->ei_flag)
+    if (!dP->bitstream->ei_flag)
       currMB->ei_flag = 0;
 
     if ((img->type==B_SLICE) && currSE.value1==0 && currSE.value2==0)
@@ -894,6 +1248,7 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
           currSE.len = (int64) 1;
           readSyntaxElement_FLC(&currSE, dP->bitstream);
           dP->bitstream->frame_bitoffset--;
+          TRACE_DECBITS(1);
           currMB->mb_field = currSE.value1;
         }
         else if(img->cod_counter > 0 && ((mb_nr&0x01) == 0))
@@ -918,12 +1273,10 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
     }
   }
 
-  dec_picture->mb_field[mb_nr] = (byte) currMB->mb_field;
+  dec_picture->motion.mb_field[mb_nr] = (byte) currMB->mb_field;
 
   img->block_y_aff = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? (mb_nr&0x01) ? (img->block_y - 4)>>1 : img->block_y >> 1 : img->block_y;
-
   img->siblock[img->mb_y][img->mb_x]=0;
-
   interpret_mb_mode(currMB);
 
   if(img->MbaffFrameFlag)
@@ -961,7 +1314,7 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
     }
     //--- init macroblock data ---
     init_macroblock       (img);
-    readMotionInfoFromNAL (currMB, img);
+    readMotionInfoFromNAL (img, currMB);
   }
 
 
@@ -1041,108 +1394,24 @@ void read_one_macroblock(Macroblock *currMB, ImageParameters *img)
 
     if (active_pps->entropy_coding_mode_flag ==CABAC)
       img->cod_counter=-1;
-
-    return;
   }
-
-  if (IS_COPY (currMB)) //keep last macroblock
+  else if (IS_COPY (currMB)) //keep last macroblock
   {
-    short pred_mv[2];
-    int zeroMotionAbove;
-    int zeroMotionLeft;
-    PixelPos mb_a, mb_b;
-    int      a_mv_y = 0;
-    int      a_ref_idx = 0;
-    int      b_mv_y = 0;
-    int      b_ref_idx = 0;
-    int      list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (mb_nr&0x01) ? 4 : 2 : 0;
-    short ***cur_mv = dec_picture->mv[LIST_0];
-    get4x4Neighbour(currMB,-1, 0, img->mb_size[IS_LUMA], &mb_a);
-    get4x4Neighbour(currMB, 0,-1, img->mb_size[IS_LUMA], &mb_b);
-
-    if (mb_a.available)
-    {
-      a_mv_y    = cur_mv[mb_a.pos_y][mb_a.pos_x][1];
-      a_ref_idx = dec_picture->ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];
-
-      if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
-      {
-        a_mv_y    /=2;
-        a_ref_idx *=2;
-      }
-      if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field)
-      {
-        a_mv_y    *=2;
-        a_ref_idx >>=1;
-      }
-    }
-
-    if (mb_b.available)
-    {
-      b_mv_y    = cur_mv[mb_b.pos_y][mb_b.pos_x][1];
-      b_ref_idx = dec_picture->ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];
-
-      if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
-      {
-        b_mv_y    /=2;
-        b_ref_idx *=2;
-      }
-      if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field)
-      {
-        b_mv_y    *=2;
-        b_ref_idx >>=1;
-      }
-    }
-
-    zeroMotionLeft  = !mb_a.available ? 1 : a_ref_idx==0 && cur_mv[mb_a.pos_y][mb_a.pos_x][0]==0 && a_mv_y==0 ? 1 : 0;
-    zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && cur_mv[mb_b.pos_y][mb_b.pos_x][0]==0 && b_mv_y==0 ? 1 : 0;
-
-    currMB->cbp = 0;
-    reset_coeffs();
-
-    img_block_y   = img->block_y;
-
-    if (zeroMotionAbove || zeroMotionLeft)
-    {
-      for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++)
-      {
-        memset(&cur_mv[j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
-      }
-    }
-    else
-    {
-      SetMotionVectorPredictor (currMB, img, pred_mv, 0, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
-
-      for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++)
-      {        
-        for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
-          memcpy(&cur_mv[j][i][0], &pred_mv[0], 2 * sizeof(short));
-      }
-    }
-    for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++)
-    {
-      memset(&dec_picture->ref_idx[LIST_0][j][img->block_x], 0, BLOCK_SIZE * sizeof(char));
-      for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
-      {        
-        dec_picture->ref_pic_id[LIST_0][j][i] =
-          dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j][i]];
-      }
-    }
-    return;
+    copy_macroblock(img, currMB);
   }
-  if(currMB->mb_type!=IPCM)
+  else if(currMB->mb_type != IPCM)
   {
     // intra prediction modes for a macroblock 4x4 **********************************************
     if (IS_INTRA(currMB))
-      read_ipred_modes(currMB, img);
+      read_ipred_modes(img, currMB);
 
     // read inter frame vector data *********************************************************
     if (IS_INTERMV (currMB) && (!IS_P8x8(currMB)))
     {
-      readMotionInfoFromNAL (currMB, img);
+      readMotionInfoFromNAL (img, currMB);
     }
     // read CBP and Coeffs  ***************************************************************
-    readCBPandCoeffsFromNAL (currMB, img);
+    readCBPandCoeffsFromNAL (img, currMB);
   }
   else
   {
@@ -1216,7 +1485,7 @@ void init_decoding_engine_IPCM(ImageParameters *img)
  ************************************************************************
  */
 
-void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP)
+static void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP)
 {
   SyntaxElement currSE;
   int i,j;
@@ -1249,6 +1518,7 @@ void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP)
       {
         readSyntaxElement_FLC(&currSE, dP->bitstream);
         img->cof[0][i][j] = currSE.value1;
+        img->fcf[0][i][j] = currSE.value1;
       }
     }
     currSE.len=img->bitdepth_chroma;
@@ -1260,7 +1530,8 @@ void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP)
         for(j=0;j<img->mb_cr_size_x;j++)
         {
           readSyntaxElement_FLC(&currSE, dP->bitstream);
-          img->cof[1][i][j] = currSE.value1;          
+          img->cof[1][i][j] = currSE.value1;
+          img->fcf[1][i][j] = currSE.value1;
         }
       }
       TRACE_STRING("pcm_sample_chroma (v)");
@@ -1269,7 +1540,8 @@ void readIPCMcoeffsFromNAL(ImageParameters *img, struct datapartition *dP)
         for(j=0;j<img->mb_cr_size_x;j++)
         {
           readSyntaxElement_FLC(&currSE, dP->bitstream);
-          img->cof[2][i][j] = currSE.value1;          
+          img->cof[2][i][j] = currSE.value1;
+          img->fcf[2][i][j] = currSE.value1;
         }
       }
     }
@@ -1294,6 +1566,7 @@ void concealIPCMcoeffs(ImageParameters *img)
     for(j=0;j<MB_BLOCK_SIZE;j++)
     {
       img->cof[0][i][j] = img->dc_pred_value_comp[0];
+      img->fcf[0][i][j] = img->dc_pred_value_comp[0];
     }
   }
 
@@ -1306,6 +1579,7 @@ void concealIPCMcoeffs(ImageParameters *img)
         for(j=0;j<img->mb_cr_size_x;j++)
         {
           img->cof[k][i][j] = img->dc_pred_value_comp[k];
+          img->fcf[k][i][j] = img->dc_pred_value_comp[k];
         }
       }
     }
@@ -1314,7 +1588,7 @@ void concealIPCMcoeffs(ImageParameters *img)
 
 
 
-void read_ipred_modes(Macroblock *currMB, ImageParameters *img)
+static void read_ipred_modes(ImageParameters *img, Macroblock *currMB)
 {
   int b8,i,j,bi,bj,bx,by,dec;
   SyntaxElement currSE;
@@ -1367,8 +1641,8 @@ void read_ipred_modes(Macroblock *currMB, ImageParameters *img)
             dP->readSyntaxElement(&currSE,img,dP);
           }
 
-          get4x4Neighbour(currMB, (bx<<2) - 1, (by<<2), img->mb_size[IS_LUMA],     &left_block);
-          get4x4Neighbour(currMB, (bx<<2),     (by<<2) - 1, img->mb_size[IS_LUMA], &top_block);
+          get4x4Neighbour(currMB, (bx<<2) - 1, (by<<2),     img->mb_size[IS_LUMA], &left_block);
+          get4x4Neighbour(currMB, (bx<<2),     (by<<2) - 1, img->mb_size[IS_LUMA], &top_block );
 
           //get from array and decode
 
@@ -1435,8 +1709,8 @@ void read_ipred_modes(Macroblock *currMB, ImageParameters *img)
  *    Set motion vector predictor
  ************************************************************************
  */
-void SetMotionVectorPredictor (Macroblock *currMB,
-                               ImageParameters  *img,
+void SetMotionVectorPredictor (ImageParameters  *img,
+                               Macroblock *currMB,                               
                                short           pred_mv[2],
                                char            ref_frame,
                                byte            list,
@@ -1454,7 +1728,7 @@ void SetMotionVectorPredictor (Macroblock *currMB,
 
   PixelPos block_a, block_b, block_c, block_d;
 
-  get4x4Neighbour(currMB, mb_x - 1,            mb_y,     img->mb_size[IS_LUMA],     &block_a);
+  get4x4Neighbour(currMB, mb_x - 1,            mb_y,     img->mb_size[IS_LUMA], &block_a);
   get4x4Neighbour(currMB, mb_x,                mb_y - 1, img->mb_size[IS_LUMA], &block_b);
   get4x4Neighbour(currMB, mb_x + blockshape_x, mb_y - 1, img->mb_size[IS_LUMA], &block_c);
   get4x4Neighbour(currMB, mb_x - 1,            mb_y - 1, img->mb_size[IS_LUMA], &block_d);
@@ -1645,7 +1919,7 @@ void SetMotionVectorPredictor (Macroblock *currMB,
  *    Read motion info
  ************************************************************************
  */
-void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img)
+static void readMotionInfoFromNAL (ImageParameters *img, Macroblock *currMB)
 {
   int i,j,k;
   int mb_nr = img->current_mb_nr;
@@ -1653,7 +1927,7 @@ void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img)
   Slice *currSlice    = img->currentSlice;
   DataPartition *dP = NULL;
   int *partMap        = assignSE2partition[currSlice->dp_mode];
-  int bframe          = (img->type==B_SLICE);
+  int bslice          = (img->type==B_SLICE);
   int partmode        = (IS_P8x8(currMB)?4:currMB->mb_type);
   int step_h0         = BLOCK_STEP [partmode][0];
   int step_v0         = BLOCK_STEP [partmode][1];
@@ -1661,197 +1935,188 @@ void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img)
   int i0, j0, j6;
 
   int j4, i4, ii;
-  static byte  **    moving_block;
-  static short ****  co_located_mv;
-  static char  ***   co_located_ref_idx;
-  static int64 ***   co_located_ref_id;
+  MotionParams *colocated;
 
   int mv_scale = 0;
 
   int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (mb_nr&0x01) ? 4 : 2 : 0;
 
 
-  if ((img->MbaffFrameFlag)&&(currMB->mb_field))
+  if (bslice)
   {
-    if(mb_nr&0x01)
+    if ((img->MbaffFrameFlag) && (currMB->mb_field))
     {
-      moving_block = Co_located->bottom_moving_block;
-      co_located_mv = Co_located->bottom_mv;
-      co_located_ref_idx = Co_located->bottom_ref_idx;
-      co_located_ref_id = Co_located->bottom_ref_pic_id;
+      if(mb_nr&0x01)
+      {
+        colocated = &Co_located->bottom;
+      }
+      else
+      {
+        colocated = &Co_located->top;
+      }
     }
     else
     {
-      moving_block = Co_located->top_moving_block;
-      co_located_mv = Co_located->top_mv;
-      co_located_ref_idx = Co_located->top_ref_idx;
-      co_located_ref_id = Co_located->top_ref_pic_id;
+      colocated = &Co_located->frame;
     }
-  }
-  else
-  {
-    moving_block = Co_located->moving_block;
-    co_located_mv = Co_located->mv;
-    co_located_ref_idx = Co_located->ref_idx;
-    co_located_ref_id = Co_located->ref_pic_id;
-  }
 
-  if (bframe && IS_P8x8 (currMB))
-  {
-    if (img->direct_spatial_mv_pred_flag)
+    if (IS_P8x8 (currMB))
     {
-      char  l0_rFrame,l1_rFrame;
-      short pmvl0[2]={0,0}, pmvl1[2]={0,0};
+      if (img->direct_spatial_mv_pred_flag)
+      {
+        char  l0_rFrame, l1_rFrame;
+        short pmvl0[2]={0,0}, pmvl1[2]={0,0};
 
-      prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
+        prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
 
-      for (k = 0; k < 4; k++)
-      {        
-        if (currMB->b8mode[k] == 0)
-        {
-          i = img->block_x + 2 * (k & 0x01);
-          for(j = 2 * (k >> 1); j < 2 * (k >> 1)+2;j++)
+        for (k = 0; k < 4; k++)
+        {        
+          if (currMB->b8mode[k] == 0)
           {
-            j6 = img->block_y_aff + j;
-            j4 = img->block_y     + j;
-            for(i4 = i; i4 < i + 2; i4++)
+            i = img->block_x + 2 * (k & 0x01);
+            for(j = 2 * (k >> 1); j < 2 * (k >> 1)+2;j++)
             {
-              if (l0_rFrame >= 0)
+              j6 = img->block_y_aff + j;
+              j4 = img->block_y     + j;
+              for(i4 = i; i4 < i + 2; i4++)
               {
-                if  (!l0_rFrame  && ((!moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                if (l0_rFrame >= 0)
                 {
-                  dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-                  dec_picture->mv  [LIST_0][j4][i4][1] = 0;
-                  dec_picture->ref_idx[LIST_0][j4][i4] = 0;
+                  if  (!l0_rFrame  && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                  {
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
+                    dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+                  }
+                  else
+                  {
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0] = pmvl0[0];
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1] = pmvl0[1];
+                    dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
+                  }
                 }
                 else
                 {
-                  dec_picture->mv  [LIST_0][j4][i4][0] = pmvl0[0];
-                  dec_picture->mv  [LIST_0][j4][i4][1] = pmvl0[1];
-                  dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame;
+                  dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+                  dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
                 }
-              }
-              else
-              {
-                dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-                dec_picture->mv  [LIST_0][j4][i4][1] = 0;
-                dec_picture->ref_idx[LIST_0][j4][i4] = -1;
-              }
 
-              if (l1_rFrame >= 0)
-              {
-                if  (l1_rFrame==0 && ((!moving_block[j6][i4])&& (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                if (l1_rFrame >= 0)
                 {
-                  dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-                  dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-                  dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+                  if  (l1_rFrame==0 && ((!colocated->moving_block[j6][i4])&& (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                  {
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+                    dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
+                  }
+                  else
+                  {
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0] = pmvl1[0];
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1] = pmvl1[1];
+                    dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
+                  }
                 }
                 else
                 {
-                  dec_picture->mv  [LIST_1][j4][i4][0] = pmvl1[0];
-                  dec_picture->mv  [LIST_1][j4][i4][1] = pmvl1[1];
-                  dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
+                  dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+                  dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
                 }
-              }
-              else
-              {
-                dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-                dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-                dec_picture->ref_idx[LIST_1][j4][i4] = -1;
-              }
 
-              if (l0_rFrame <0 && l1_rFrame <0)
-              {
-                dec_picture->ref_idx[LIST_0][j4][i4] = 0;
-                dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+                if (l0_rFrame <0 && l1_rFrame <0)
+                {
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
+                }
               }
             }
           }
         }
       }
-    }
-    else
-    {
-      for (k = 0; k < 4; k++) // Scan all blocks
+      else
       {
-        if (currMB->b8mode[k] == 0)
+        for (k = 0; k < 4; k++) // Scan all blocks
         {
-          for(j0 = 2 * (k >> 1); j0 < 2 * (k >> 1) + 2; j0 += step_v0)
+          if (currMB->b8mode[k] == 0)
           {
-            for(i0 = img->block_x + 2*(k & 0x01); i0 < img->block_x + 2 * (k & 0x01)+2; i0 += step_h0)
+            for(j0 = 2 * (k >> 1); j0 < 2 * (k >> 1) + 2; j0 += step_v0)
             {
-              int refList = co_located_ref_idx[LIST_0 ][img->block_y_aff + j0][i0]== -1 ? LIST_1 : LIST_0;
-              int ref_idx = co_located_ref_idx[refList][img->block_y_aff + j0][i0];
-              int mapped_idx = -1, iref;
-
-              if (ref_idx == -1)
+              for(i0 = img->block_x + 2*(k & 0x01); i0 < img->block_x + 2 * (k & 0x01)+2; i0 += step_h0)
               {
-                for (j4 = img->block_y + j0; j4 < img->block_y + j0 + step_v0; j4++)
+                int refList = colocated->ref_idx[LIST_0 ][img->block_y_aff + j0][i0]== -1 ? LIST_1 : LIST_0;
+                int ref_idx = colocated->ref_idx[refList][img->block_y_aff + j0][i0];
+                int mapped_idx = -1, iref;
+
+                if (ref_idx == -1)
                 {
-                  memset(&dec_picture->ref_idx [LIST_0][j4][i0],    0,     step_h0 * sizeof(char));
-                  memset(&dec_picture->ref_idx [LIST_1][j4][i0],    0,     step_h0 * sizeof(char));
-                  memset(&dec_picture->mv      [LIST_0][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
-                  memset(&dec_picture->mv      [LIST_1][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
+                  for (j4 = img->block_y + j0; j4 < img->block_y + j0 + step_v0; j4++)
+                  {
+                    memset(&dec_picture->motion.ref_idx [LIST_0][j4][i0],    0,     step_h0 * sizeof(char));
+                    memset(&dec_picture->motion.ref_idx [LIST_1][j4][i0],    0,     step_h0 * sizeof(char));
+                    memset(&dec_picture->motion.mv      [LIST_0][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
+                    memset(&dec_picture->motion.mv      [LIST_1][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
+                  }
                 }
-              }
-              else
-              {
-                for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]); iref++)
+                else
                 {
-                  int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
-
-                  if(img->structure==0 && curr_mb_field==0)
+                  for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]); iref++)
                   {
-                    // If the current MB is a frame MB and the colocated is from a field picture,
-                    // then the co_located_ref_id may have been generated from the wrong value of
-                    // frame_poc if it references it's complementary field, so test both POC values
-                    if(listX[0][iref]->top_poc * 2    == co_located_ref_id[refList][img->block_y_aff + j0][i0]
-                    || listX[0][iref]->bottom_poc * 2 == co_located_ref_id[refList][img->block_y_aff + j0][i0])
+                    int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
+
+                    if(img->structure==0 && curr_mb_field==0)
+                    {
+                      // If the current MB is a frame MB and the colocated is from a field picture,
+                      // then the colocated->ref_pic_id may have been generated from the wrong value of
+                      // frame_poc if it references it's complementary field, so test both POC values
+                      if(listX[0][iref]->top_poc * 2    == colocated->ref_pic_id[refList][img->block_y_aff + j0][i0]
+                      || listX[0][iref]->bottom_poc * 2 == colocated->ref_pic_id[refList][img->block_y_aff + j0][i0])
+                      {
+                        mapped_idx=iref;
+                        break;
+                      }
+                      else //! invalid index. Default to zero even though this case should not happen
+                        mapped_idx=INVALIDINDEX;
+                      continue;
+                    }
+                    if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==colocated->ref_pic_id[refList][img->block_y_aff + j0][i0])
                     {
                       mapped_idx=iref;
                       break;
                     }
                     else //! invalid index. Default to zero even though this case should not happen
                       mapped_idx=INVALIDINDEX;
-                    continue;
                   }
-                  if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][img->block_y_aff + j0][i0])
+
+                  if (INVALIDINDEX == mapped_idx)
                   {
-                    mapped_idx=iref;
-                    break;
+                    error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
                   }
-                  else //! invalid index. Default to zero even though this case should not happen
-                    mapped_idx=INVALIDINDEX;
-                }
-                
-                if (INVALIDINDEX == mapped_idx)
-                {
-                  error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
-                }
-
-                for (j = j0; j < j0 + step_v0; j++)
-                {
-                  j4 = img->block_y + j;
-                  j6 = img->block_y_aff + j;
 
-                  for (i4 = i0; i4 < i0 + step_h0; i4++)
+                  for (j = j0; j < j0 + step_v0; j++)
                   {
-                    mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
-
-                    dec_picture->ref_idx [LIST_0][j4][i4] = (char) mapped_idx;
-                    dec_picture->ref_idx [LIST_1][j4][i4] = 0;
+                    j4 = img->block_y + j;
+                    j6 = img->block_y_aff + j;
 
-                    for (ii=0; ii < 2; ii++)
+                    for (i4 = i0; i4 < i0 + step_h0; i4++)
                     {
-                      if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
-                      {
-                        dec_picture->mv  [LIST_0][j4][i4][ii] = co_located_mv[refList][j6][i4][ii];
-                        dec_picture->mv  [LIST_1][j4][i4][ii] = 0;
-                      }
-                      else
+                      mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
+
+                      dec_picture->motion.ref_idx [LIST_0][j4][i4] = (char) mapped_idx;
+                      dec_picture->motion.ref_idx [LIST_1][j4][i4] = 0;
+
+                      for (ii=0; ii < 2; ii++)
                       {
-                        dec_picture->mv  [LIST_0][j4][i4][ii] = (short) ((mv_scale * co_located_mv[refList][j6][i4][ii] + 128 ) >> 8);
-                        dec_picture->mv  [LIST_1][j4][i4][ii] = (short) (dec_picture->mv[LIST_0][j4][i4][ii] - co_located_mv[refList][j6][i4][ii]);
+                        if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
+                        {
+                          dec_picture->motion.mv  [LIST_0][j4][i4][ii] = colocated->mv[refList][j6][i4][ii];
+                          dec_picture->motion.mv  [LIST_1][j4][i4][ii] = 0;
+                        }
+                        else
+                        {
+                          dec_picture->motion.mv  [LIST_0][j4][i4][ii] = (short) ((mv_scale * colocated->mv[refList][j6][i4][ii] + 128 ) >> 8);
+                          dec_picture->motion.mv  [LIST_1][j4][i4][ii] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][ii] - colocated->mv[refList][j6][i4][ii]);
+                        }
                       }
                     }
                   }
@@ -1868,12 +2133,12 @@ void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img)
   currSE.type = SE_REFFRAME;
   dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);
   //  For LIST_0, if multiple ref. pictures, read LIST_0 reference picture indices for the MB ***********
-  prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l0_active, !IS_P8x8 (currMB) || bframe || (!img->allrefzero));
-  readMBRefPictureIdx  (&currSE, dP, currMB, img, &dec_picture->ref_idx[LIST_0][img->block_y], LIST_0, step_v0, step_h0);
+  prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l0_active, !IS_P8x8 (currMB) || bslice || (!img->allrefzero));
+  readMBRefPictureIdx  (&currSE, dP, currMB, img, &dec_picture->motion.ref_idx[LIST_0][img->block_y], LIST_0, step_v0, step_h0);
 
   //  For LIST_1, if multiple ref. pictures, read LIST_1 reference picture indices for the MB ***********
-  prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l1_active, !IS_P8x8 (currMB) || bframe || (!img->allrefzero));
-  readMBRefPictureIdx  (&currSE, dP, currMB, img, &dec_picture->ref_idx[LIST_1][img->block_y], LIST_1, step_v0, step_h0);
+  prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l1_active, !IS_P8x8 (currMB) || bslice || (!img->allrefzero));
+  readMBRefPictureIdx  (&currSE, dP, currMB, img, &dec_picture->motion.ref_idx[LIST_1][img->block_y], LIST_1, step_v0, step_h0);
 
   //=====  READ MOTION VECTORS =====
   currSE.type = SE_MVD;
@@ -1887,20 +2152,21 @@ void readMotionInfoFromNAL (Macroblock *currMB, ImageParameters *img)
   // LIST_0 Motion vectors
   readMBMotionVectors (&currSE, dP, currMB, img, LIST_0, step_h0, step_v0);
   // LIST_1 Motion vectors
-  readMBMotionVectors (&currSE, dP, currMB, img, LIST_1, step_h0, step_v0);
+  if (bslice)
+    readMBMotionVectors (&currSE, dP, currMB, img, LIST_1, step_h0, step_v0);
 
   // record reference picture Ids for deblocking decisions
 
-  for (k = LIST_0; k <= LIST_1; k++)
+  for (k = LIST_0; k <= (bslice ? LIST_1: LIST_0); k++)
   {
     for(j4 = img->block_y; j4 < (img->block_y +4);j4++)
     {
       for(i4 = img->block_x; i4 < (img->block_x + 4);i4++)
       {
-        if (dec_picture->ref_idx[k][j4][i4]>=0)
-          dec_picture->ref_pic_id[k][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][k + list_offset][(short)dec_picture->ref_idx[k][j4][i4]];
+        if (dec_picture->motion.ref_idx[k][j4][i4]>=0)
+          dec_picture->motion.ref_pic_id[k][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][k + list_offset][(short)dec_picture->motion.ref_idx[k][j4][i4]];
         else
-          dec_picture->ref_pic_id[k][j4][i4] = INT64_MIN;
+          dec_picture->motion.ref_pic_id[k][j4][i4] = INT64_MIN;
       }
     }
   }
@@ -1937,15 +2203,15 @@ int predict_nnz(Macroblock *currMB, int block_type, ImageParameters *img, int i,
     switch (block_type)
     {
     case LUMA:
-      pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][pix.y];
+      pred_nnz = img->nz_coeff [pix.mb_addr ][0][pix.y][pix.x];
       cnt++;
       break;
     case CB:
-      pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][4+pix.y];
+      pred_nnz = img->nz_coeff [pix.mb_addr ][1][pix.y][pix.x];
       cnt++;
       break;
     case CR:
-      pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][8+pix.y];
+      pred_nnz = img->nz_coeff [pix.mb_addr ][2][pix.y][pix.x];
       cnt++;
       break;
     default:
@@ -1969,15 +2235,15 @@ int predict_nnz(Macroblock *currMB, int block_type, ImageParameters *img, int i,
     switch (block_type)
     {
     case LUMA:
-      pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][pix.y];
+      pred_nnz += img->nz_coeff [pix.mb_addr ][0][pix.y][pix.x];
       cnt++;
       break;
     case CB:
-      pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][4+pix.y];
+      pred_nnz += img->nz_coeff [pix.mb_addr ][1][pix.y][pix.x];
       cnt++;
       break;
     case CR:
-      pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][8+pix.y];
+      pred_nnz += img->nz_coeff [pix.mb_addr ][2][pix.y][pix.x];
       cnt++;
       break;
     default:
@@ -2010,13 +2276,13 @@ int predict_nnz_chroma(Macroblock *currMB, ImageParameters *img, int i,int j)
   PixelPos pix;
 
   int pred_nnz = 0;
-  int cnt      =0;
+  int cnt      = 0;
 
   if (dec_picture->chroma_format_idc != YUV444)
   {
     //YUV420 and YUV422
     // left block
-    get4x4Neighbour(currMB, ((i&0x01)<<2) - 1, ((j-4)<<2), img->mb_size[IS_CHROMA], &pix);
+    get4x4Neighbour(currMB, ((i&0x01)<<2) - 1, j, img->mb_size[IS_CHROMA], &pix);
 
     if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
     {
@@ -2027,12 +2293,12 @@ int predict_nnz_chroma(Macroblock *currMB, ImageParameters *img, int i,int j)
 
     if (pix.available)
     {
-      pred_nnz = img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y];
+      pred_nnz = img->nz_coeff [pix.mb_addr ][1][pix.y][2 * (i>>1) + pix.x];
       cnt++;
     }
 
     // top block
-    get4x4Neighbour(currMB, ((i&0x01)<<2), ((j-4)<<2) - 1, img->mb_size[IS_CHROMA], &pix);
+    get4x4Neighbour(currMB, ((i&0x01)<<2), j - 1, img->mb_size[IS_CHROMA], &pix);
 
     if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
     {
@@ -2043,15 +2309,15 @@ int predict_nnz_chroma(Macroblock *currMB, ImageParameters *img, int i,int j)
 
     if (pix.available)
     {
-      pred_nnz += img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y];
+      pred_nnz += img->nz_coeff [pix.mb_addr ][1][pix.y][2 * (i>>1) + pix.x];
       cnt++;
     }
-  }
 
-  if (cnt==2)
-  {
-    pred_nnz++;
-    pred_nnz>>=1;
+    if (cnt==2)
+    {
+      pred_nnz++;
+      pred_nnz >>= 1;
+    }
   }
 
   return pred_nnz;
@@ -2095,97 +2361,75 @@ void readCoeff4x4_CAVLC (Macroblock *currMB, ImageParameters *img,
   {
   case LUMA:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Luma");
-#endif
+    TRACE_PRINTF("Luma");
     dptype = IS_INTRA (currMB) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   case LUMA_INTRA16x16DC:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Lum16DC");
-#endif
+    TRACE_PRINTF("Lum16DC");
     dptype = SE_LUM_DC_INTRA;
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   case LUMA_INTRA16x16AC:
     max_coeff_num = 15;
-#if TRACE
-    sprintf(type, "%s", "Lum16AC");
-#endif
+    TRACE_PRINTF("Lum16AC");
     dptype = SE_LUM_AC_INTRA;
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   case CB:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Luma_add1");
-#endif
+    TRACE_PRINTF("Luma_add1");
     dptype = (IS_INTRA (currMB)) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
-    img->nz_coeff[mb_nr][i][4+j] = 0; 
+    img->nz_coeff[mb_nr][1][j][i] = 0; 
     break;
   case CB_INTRA16x16DC:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Luma_add1_16DC");
-#endif
+    TRACE_PRINTF("Luma_add1_16DC");
     dptype = SE_LUM_DC_INTRA;
-    img->nz_coeff[mb_nr][i][j+4] = 0; 
+    img->nz_coeff[mb_nr][1][j][i] = 0; 
     break;
   case CB_INTRA16x16AC:
     max_coeff_num = 15;
-#if TRACE
-    sprintf(type, "%s", "Luma_add1_16AC");
-#endif
+    TRACE_PRINTF("Luma_add1_16AC");
     dptype = SE_LUM_AC_INTRA;
-    img->nz_coeff[mb_nr][i][4+j] = 0; 
+    img->nz_coeff[mb_nr][1][j][i] = 0; 
     break;
   case CR:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Luma_add2");
-#endif
+    TRACE_PRINTF("Luma_add2");
     dptype = (IS_INTRA (currMB)) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
-    img->nz_coeff[mb_nr][i][8+j] = 0; 
+    img->nz_coeff[mb_nr][2][j][i] = 0; 
     break;
   case CR_INTRA16x16DC:
     max_coeff_num = 16;
-#if TRACE
-    sprintf(type, "%s", "Luma_add2_16DC");
-#endif
+    TRACE_PRINTF("Luma_add2_16DC");
     dptype = SE_LUM_DC_INTRA;
-    img->nz_coeff[mb_nr][i][8+j] = 0; 
+    img->nz_coeff[mb_nr][2][j][i] = 0; 
     break;
   case CR_INTRA16x16AC:
     max_coeff_num = 15;
-#if TRACE
-    sprintf(type, "%s", "LumA_add2_16AC");
-#endif
+    TRACE_PRINTF("Luma_add1_16AC");
     dptype = SE_LUM_AC_INTRA;
-    img->nz_coeff[mb_nr][i][8+j] = 0; 
+    img->nz_coeff[mb_nr][2][j][i] = 0; 
     break;        
   case CHROMA_DC:
     max_coeff_num = img->num_cdc_coeff;
     cdc = 1;
-#if TRACE
-    sprintf(type, "%s", "ChrDC");
-#endif
+    TRACE_PRINTF("ChrDC");
     dptype = IS_INTRA (currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER;
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   case CHROMA_AC:
     max_coeff_num = 15;
     cac = 1;
-#if TRACE
-    sprintf(type, "%s", "ChrAC");
-#endif
+    TRACE_PRINTF("ChrDC");
     dptype = IS_INTRA (currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER;
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   default:
     error ("readCoeff4x4_CAVLC: invalid block type", 600);
-    img->nz_coeff[mb_nr][i][j] = 0; 
+    img->nz_coeff[mb_nr][0][j][i] = 0; 
     break;
   }
   
@@ -2198,7 +2442,7 @@ void readCoeff4x4_CAVLC (Macroblock *currMB, ImageParameters *img,
     // luma or chroma AC    
     if(block_type==LUMA || block_type==LUMA_INTRA16x16DC || block_type==LUMA_INTRA16x16AC ||block_type==CHROMA_AC)
     {
-      nnz = (!cac) ? predict_nnz(currMB, LUMA, img, i<<2, j<<2) : predict_nnz_chroma(currMB, img, i, j);
+      nnz = (!cac) ? predict_nnz(currMB, LUMA, img, i<<2, j<<2) : predict_nnz_chroma(currMB, img, i, ((j-4)<<2));
     }
     else if (block_type==CB || block_type==CB_INTRA16x16DC || block_type==CB_INTRA16x16AC)
     {   
@@ -2234,11 +2478,11 @@ void readCoeff4x4_CAVLC (Macroblock *currMB, ImageParameters *img,
     numtrailingones =  currSE.value2;
     
     if(block_type==LUMA || block_type==LUMA_INTRA16x16DC || block_type==LUMA_INTRA16x16AC ||block_type==CHROMA_AC)
-      img->nz_coeff[mb_nr][i][j] = numcoeff;
+      img->nz_coeff[mb_nr][0][j][i] = numcoeff;
     else if (block_type==CB || block_type==CB_INTRA16x16DC || block_type==CB_INTRA16x16AC)
-      img->nz_coeff[mb_nr][i][4+j] = numcoeff;
+      img->nz_coeff[mb_nr][1][j][i] = numcoeff;
     else
-      img->nz_coeff[mb_nr][i][8+j] = numcoeff;        
+      img->nz_coeff[mb_nr][2][j][i] = numcoeff;        
   }
   else
   {
@@ -2366,44 +2610,6 @@ void readCoeff4x4_CAVLC (Macroblock *currMB, ImageParameters *img,
 
 
 
-/*!
- ************************************************************************
- * \brief
- *    Calculate the quantisation and inverse quantisation parameters
- *
- ************************************************************************
- */
-void CalculateQuant8Param()
-{
-  int i, j, k, temp;
-
-  for(k=0; k<6; k++)
-    for(i=0; i<8; i++)
-    {
-      for(j=0; j<8; j++)
-      {
-        temp = (i<<3)+j;
-        InvLevelScale8x8Luma_Intra[k][i][j] = dequant_coef8[k][i][j] * qmatrix[6][temp];
-        InvLevelScale8x8Luma_Inter[k][i][j] = dequant_coef8[k][i][j] * qmatrix[7][temp];
-      }
-    }
-
-    if( active_sps->chroma_format_idc == 3 )  // 4:4:4
-    {
-      for(k=0; k<6; k++)
-        for(i=0; i<8; i++)
-        {
-          for(j=0; j<8; j++)
-          {
-            temp = (i<<3)+j;
-            InvLevelScale8x8Chroma_Intra[0][k][i][j] = dequant_coef8[k][i][j] * qmatrix[8][temp];
-            InvLevelScale8x8Chroma_Inter[0][k][i][j] = dequant_coef8[k][i][j] * qmatrix[9][temp];
-            InvLevelScale8x8Chroma_Intra[1][k][i][j] = dequant_coef8[k][i][j] * qmatrix[10][temp];
-            InvLevelScale8x8Chroma_Inter[1][k][i][j] = dequant_coef8[k][i][j] * qmatrix[11][temp];
-          }
-        }
-    }
-}
 
 /*!
 ************************************************************************
@@ -2412,7 +2618,7 @@ void CalculateQuant8Param()
 *    from the NAL (CABAC Mode)
 ************************************************************************
 */
-void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters *img, int b8)
+static void readLumaCoeff8x8_CABAC (ImageParameters *img, Macroblock *currMB, ColorPlane pl, int b8)
 {
   static int (*tcoeffs)[16];
   int i,j,k;
@@ -2422,58 +2628,41 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
   Slice *currSlice = img->currentSlice;
   DataPartition *dP;
   int *partMap = assignSE2partition[currSlice->dp_mode];
-  int start_scan = 0; // take all coeffs
-  int coef_ctr = start_scan - 1;// i0, j0;
   int boff_x, boff_y;
 
-  int run;
-
-  int qp, qp_c, qp_per, qp_rem; 
-  int uv = pl-1; 
+  int qp_per, qp_rem; 
+  int uv = pl - 1; 
   int64 cbp_mask = (int64) 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position            
   int64 *cur_cbp;
 
   Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
   int (*InvLevelScale8x8)[8] = NULL;
   // select scan type
-  const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8;
+  const byte (*pos_scan8x8) = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8[0] : FIELD_SCAN8x8[0];
 
   if (cbp & (1<<b8))  // are there any coefficients in the current block
   {
     if (pl)
     {
-      qp = img->qp + dec_picture->chroma_qp_offset[uv];
-      qp = iClip3(-(img->bitdepth_chroma_qp_scale), 51, qp); 
-      qp_c  = (qp < 0)? qp : QP_SCALE_CR[qp-MIN_QP];
-      qp_per = (qp_c + img->bitdepth_chroma_qp_scale)/6;
-      qp_rem = (qp_c + img->bitdepth_chroma_qp_scale)%6;
+      qp_per  = qp_per_matrix[ currMB->qp_scaled[pl] ];
+      qp_rem  = qp_rem_matrix[ currMB->qp_scaled[pl] ];
       cur_cbp = &currMB->cbp_blk;
     }
     else
     {
-      qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
-      qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
+      qp_per  = qp_per_matrix[ currMB->qp_scaled[pl] ];
+      qp_rem  = qp_rem_matrix[ currMB->qp_scaled[pl] ];
       cur_cbp = &currMB->cbp_blk_CbCr[uv];
     }
 
-    if( IS_INDEPENDENT(img) )
-    {
-      if( img->colour_plane_id == 0 )
-        InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
-      else if( img->colour_plane_id == 1 )
-        InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8Chroma_Intra[0][qp_rem] : InvLevelScale8x8Chroma_Inter[0][qp_rem];
-      else if( img->colour_plane_id == 2 )
-        InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8Chroma_Intra[1][qp_rem] : InvLevelScale8x8Chroma_Inter[1][qp_rem];
-    }
-    else
-      InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
+    InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8_Intra[pl][qp_rem] : InvLevelScale8x8_Inter[pl][qp_rem];
 
     img->is_intra_block = IS_INTRA(currMB);
 
     // === set offset in current macroblock ===
     boff_x = (b8&0x01) << 3;
     boff_y = (b8 >> 1) << 3;
-    tcoeffs = &img->m7[pl][boff_y];
+    tcoeffs = &img->mb_rres[pl][boff_y];
 
     img->subblock_x = boff_x >> 2; // position for coeff_count ctx
     img->subblock_y = boff_y >> 2; // position for coeff_count ctx
@@ -2508,21 +2697,20 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
       //============ decode =============
       if (level != 0)    /* leave if len=1 */
       {
-        coef_ctr += currSE.value2 + 1;
         *cur_cbp |= cbp_mask; 
-        i=pos_scan8x8[coef_ctr][0];
-        j=pos_scan8x8[coef_ctr][1];
+
+        pos_scan8x8 += 2 * (currSE.value2);
+
+        i = *pos_scan8x8++;
+        j = *pos_scan8x8++;
 
         tcoeffs[j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization
-      }
 
-      if (level != 0)
-      {
         // AC coefficients
         currSE.type    = ((img->is_intra_block == 1) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER);
         dP = &(currSlice->partArr[partMap[currSE.type]]);
 
-        for(k=1;(k < 65) && (level != 0);k++)
+        for(k = 1;(k < 65) && (level != 0);k++)
         {
 #if TRACE
           if (pl==PLANE_Y)
@@ -2539,10 +2727,10 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
           //============ decode =============
           if (level != 0)    /* leave if len=1 */
           {
-            coef_ctr += currSE.value2 + 1;
+            pos_scan8x8 += 2 * (currSE.value2);
 
-            i=pos_scan8x8[coef_ctr][0];
-            j=pos_scan8x8[coef_ctr][1];          
+            i = *pos_scan8x8++;
+            j = *pos_scan8x8++;
 
             tcoeffs[ j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization
           }
@@ -2551,7 +2739,7 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
     }
     else
     {
-      for(k=start_scan;(k < 65) && (level != 0);k++)
+      for(k=0; (k < 65) && (level != 0);k++)
       {
         //============ read =============
         /*
@@ -2577,16 +2765,14 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
 
         dP->readSyntaxElement(&currSE,img,dP);
         level = currSE.value1;
-        run   = currSE.value2;
-        //len   = currSE.len;
 
         //============ decode =============
         if (level != 0)    /* leave if len=1 */
         {
-          coef_ctr += run + 1;
+          pos_scan8x8 += 2 * (currSE.value2);
 
-          i=pos_scan8x8[coef_ctr][0];
-          j=pos_scan8x8[coef_ctr][1];
+          i = *pos_scan8x8++;
+          j = *pos_scan8x8++;
 
           *cur_cbp |= cbp_mask; 
 
@@ -2605,7 +2791,7 @@ void readLumaCoeff8x8_CABAC (Macroblock *currMB, ColorPlane pl, ImageParameters
  *    is missing.
  ************************************************************************
  */
-void check_dp_neighbors (Macroblock *currMB)
+static void check_dp_neighbors (Macroblock *currMB)
 {
   PixelPos up, left;
 
@@ -2633,7 +2819,7 @@ void check_dp_neighbors (Macroblock *currMB)
  *    from the NAL
  ************************************************************************
  */
-void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
+static void readCBPandCoeffsFromNAL(ImageParameters *img, Macroblock *currMB)
 {
   int i,j,k;
   int level;
@@ -2642,7 +2828,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   int cbp;
   SyntaxElement currSE;
   Slice *currSlice = img->currentSlice;
-  DataPartition *dP;
+  DataPartition *dP = NULL;
   int *partMap = assignSE2partition[currSlice->dp_mode];
   int coef_ctr, i0, j0, b8;
   int ll;
@@ -2650,8 +2836,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   int start_scan;
   int levarr[16], runarr[16], numcoeff;
   
-  int qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
-  int qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
+  int qp_per    = qp_per_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
+  int qp_rem    = qp_rem_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
   int smb       = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
   
   int uv; 
@@ -2663,7 +2849,6 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   
   int b4;
   int yuv = dec_picture->chroma_format_idc - 1;
-  int m5[4];
   int m6[4];
   
   int need_transform_size_flag;
@@ -2674,6 +2859,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   // select scan type
   const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8;
   const byte (*pos_scan4x4)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN : FIELD_SCAN;
+  const byte *pos_scan_4x4 = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN[0] : FIELD_SCAN[0];
 
   if(img->type==SP_SLICE  && currMB->mb_type!=I16MB )
     smb=1;
@@ -2684,8 +2870,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   {
     for (i=0; i<2; i++)
     {
-      qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6;
-      qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6;
+      qp_per_uv[i] = qp_per_matrix[ currMB->qp_scaled[i + 1] ];
+      qp_rem_uv[i] = qp_rem_matrix[ currMB->qp_scaled[i + 1] ];
     }
   }
   
@@ -2712,7 +2898,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     }
     
     TRACE_STRING("coded_block_pattern");
-    dP->readSyntaxElement(&currSE,img,dP);
+    dP->readSyntaxElement(&currSE, img, dP);
     currMB->cbp = cbp = currSE.value1;
     
     
@@ -2750,27 +2936,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     // Delta quant only if nonzero coeffs
     if (cbp !=0)
     {
-      currSE.type = (IS_INTER (currMB)) ? SE_DELTA_QUANT_INTER : SE_DELTA_QUANT_INTRA;
+      read_delta_quant(&currSE, dP, currSlice, img, currMB, partMap, (IS_INTER (currMB)) ? SE_DELTA_QUANT_INTER : SE_DELTA_QUANT_INTRA);
 
-      dP = &(currSlice->partArr[partMap[currSE.type]]);
-
-      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
-      {
-        currSE.mapping = linfo_se;
-      }
-      else
-        currSE.reading= readDquant_CABAC;
-
-      TRACE_STRING("mb_qp_delta");
-
-      dP->readSyntaxElement(&currSE,img,dP);
-      currMB->delta_quant = currSE.value1;
-      if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2)))
-        error ("mb_qp_delta is out of range", 500);
-
-      img->qp = ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) -
-        img->bitdepth_luma_qp_scale;
-      
       if (currSlice->dp_mode)
       {
         if (IS_INTER (currMB) && currSlice->dpC_NotPresent ) 
@@ -2798,32 +2965,12 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   }
   
   memset(&img->cof[0][0][0], 0, MB_PIXELS * sizeof(int)); // reset luma coeffs   
+  memset(&img->fcf[0][0][0], 0, MB_PIXELS * sizeof(int)); // reset luma coeffs   
     
   if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes
   {
-    currSE.type = SE_DELTA_QUANT_INTRA;
-    
-    dP = &(currSlice->partArr[partMap[currSE.type]]);
-    
-    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
-    {
-      currSE.mapping = linfo_se;
-    }
-    else
-    {
-      currSE.reading= readDquant_CABAC;
-    }
-#if TRACE
-    snprintf(currSE.tracestring, TRACESTRING_SIZE, "Delta quant ");
-#endif
-    dP->readSyntaxElement(&currSE,img,dP);
-    currMB->delta_quant = currSE.value1;
-    if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2)))
-      error ("mb_qp_delta is out of range", 500);
-    
-    img->qp= ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) -
-      img->bitdepth_luma_qp_scale;
-    
+    read_delta_quant(&currSE, dP, currSlice, img, currMB, partMap, SE_DELTA_QUANT_INTRA);
+
     for (j=0;j<BLOCK_SIZE;j++)
       memset(&img->ipredmode[img->block_y+j][img->block_x], DC_PRED,  BLOCK_SIZE * sizeof(byte));
         
@@ -2837,30 +2984,29 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
       check_dp_neighbors (currMB);
       if (currMB->dpl_flag)
       {
-        cbp =0; 
-        currMB->cbp      = cbp;
+        currMB->cbp = cbp = 0; 
       }
     }
 
     if (!currMB->dpl_flag)
     {
+      pos_scan_4x4 = pos_scan4x4[0];
+
       if (active_pps->entropy_coding_mode_flag == UVLC)
       {
-        readCoeff4x4_CAVLC(currMB, img, LUMA_INTRA16x16DC, 0, 0,
-          levarr, runarr, &numcoeff);
+        readCoeff4x4_CAVLC(currMB, img, LUMA_INTRA16x16DC, 0, 0, levarr, runarr, &numcoeff);
 
-        coef_ctr=-1;
-        level = 1;                            // just to get inside the loop
         for(k = 0; k < numcoeff; k++)
         {
           if (levarr[k] != 0)                     // leave if len=1
           {
-            coef_ctr += runarr[k] + 1;
+            pos_scan_4x4 += 2 * runarr[k];
 
-            i0=pos_scan4x4[coef_ctr][0];
-            j0=pos_scan4x4[coef_ctr][1];
+            i0 = ((*pos_scan_4x4++) << 2);
+            j0 = ((*pos_scan_4x4++) << 2);
 
-            img->cof[0][j0<<2][i0<<2]=levarr[k];// add new intra DC coeff
+            img->cof[0][j0][i0] = levarr[k];// add new intra DC coeff
+            img->fcf[0][j0][i0] = levarr[k];// add new intra DC coeff
           }
         }
       }
@@ -2882,7 +3028,6 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
           currSE.reading = readRunLevel_CABAC;
         }
 
-        coef_ctr = -1;
         level = 1;                            // just to get inside the loop
 
         for(k=0;(k<17) && (level!=0);k++)
@@ -2890,66 +3035,44 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 #if TRACE
           snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC luma 16x16 ");
 #endif
-          dP->readSyntaxElement(&currSE,img,dP);
+          dP->readSyntaxElement(&currSE, img, dP);
           level = currSE.value1;
-          //run   = currSE.value2;
-          //len   = currSE.len;
 
           if (level != 0)                     // leave if len=1
           {
-            coef_ctr += (currSE.value2 + 1);
+            pos_scan_4x4 += (2 * currSE.value2);
 
-            i0 = pos_scan4x4[coef_ctr][0];
-            j0 = pos_scan4x4[coef_ctr][1];
+            i0 = ((*pos_scan_4x4++) << 2);
+            j0 = ((*pos_scan_4x4++) << 2);
 
-            img->cof[0][j0<<2][i0<<2] = level;// add new intra DC coeff
+            img->cof[0][j0][i0] = level;// add new intra DC coeff
+            img->fcf[0][j0][i0] = level;// add new intra DC coeff
           }
         }
       }
+
       if(!lossless_qpprime)
-        itrans_2(PLANE_Y, img);// transform new intra DC
+        itrans_2(img, currMB, PLANE_Y);// transform new intra DC
     }
   }
-  currMB->qp = img->qp;
-  set_chroma_qp(currMB);
-  
-  qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
-  qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
+  update_qp(img, currMB, img->qp);
   
-  if( IS_INDEPENDENT(img) )
-  {
-    if( img->colour_plane_id == 0 )
-    {
-      InvLevelScale4x4 = intra? InvLevelScale4x4Luma_Intra[qp_rem] : InvLevelScale4x4Luma_Inter[qp_rem];
-      InvLevelScale8x8 = intra? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
-    }
-    else if( img->colour_plane_id == 1 )
-    {
-      InvLevelScale4x4 = intra? InvLevelScale4x4Chroma_Intra[0][qp_rem] : InvLevelScale4x4Chroma_Inter[0][qp_rem];
-      InvLevelScale8x8 = intra? InvLevelScale8x8Chroma_Intra[0][qp_rem] : InvLevelScale8x8Chroma_Inter[0][qp_rem];
-    }
-    else if( img->colour_plane_id == 2 )
-    {
-      InvLevelScale4x4 = intra? InvLevelScale4x4Chroma_Intra[1][qp_rem] : InvLevelScale4x4Chroma_Inter[1][qp_rem];
-      InvLevelScale8x8 = intra? InvLevelScale8x8Chroma_Intra[1][qp_rem] : InvLevelScale8x8Chroma_Inter[1][qp_rem];
-    }
-  }
-  else
-  {
-    InvLevelScale4x4 = intra? InvLevelScale4x4Luma_Intra[qp_rem] : InvLevelScale4x4Luma_Inter[qp_rem];
-    InvLevelScale8x8 = intra? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
-  }
-    
-  //init constants for every chroma qp offset
+  qp_per = qp_per_matrix[ currMB->qp_scaled[img->colour_plane_id] ];
+  qp_rem = qp_rem_matrix[ currMB->qp_scaled[img->colour_plane_id] ];
+
+  //init quant parameters for chroma 
   if (dec_picture->chroma_format_idc != YUV400)
   {
     for(i=0; i < 2; i++)
     {
-      qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6;
-      qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6;
+      qp_per_uv[i] = qp_per_matrix[ currMB->qp_scaled[i + 1] ];
+      qp_rem_uv[i] = qp_rem_matrix[ currMB->qp_scaled[i + 1] ];
     }
   }
-      
+
+  InvLevelScale4x4 = intra? InvLevelScale4x4_Intra[img->colour_plane_id][qp_rem] : InvLevelScale4x4_Inter[img->colour_plane_id][qp_rem];
+  InvLevelScale8x8 = intra? InvLevelScale8x8_Intra[img->colour_plane_id][qp_rem] : InvLevelScale8x8_Inter[img->colour_plane_id][qp_rem];
+    
   // luma coefficients
   if (active_pps->entropy_coding_mode_flag == UVLC)
   {
@@ -2959,106 +3082,115 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     {
       if (!currMB->luma_transform_size_8x8_flag) // 4x4 transform
       {
-        int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
-        for (block_y=0; block_y < 4; block_y += 2) /* all modes */
+        if (cbp)
         {
-          for (block_x=0; block_x < 4; block_x += 2)
+          int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
+          for (block_y=0; block_y < 4; block_y += 2) /* all modes */
           {
-            b8 = (block_y + (block_x >> 1));
-            
-            if (cbp & (1 << b8))  // test if the block contains any coefficients
+            for (block_x=0; block_x < 4; block_x += 2)
             {
-              for (j=block_y; j < block_y+2; j++)
+              b8 = (block_y + (block_x >> 1));
+
+              if (cbp & (1 << b8))  // test if the block contains any coefficients
               {
-                for (i=block_x; i < block_x+2; i++)
+                for (j=block_y; j < block_y + 2; j++)
                 {
-                  readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
-
-                  coef_ctr = start_scan - 1;
-
-                  for (k = 0; k < numcoeff; k++)
+                  for (i=block_x; i < block_x + 2; i++)
                   {
-                    if (levarr[k] != 0)
+                    readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
+                    pos_scan_4x4 = pos_scan4x4[start_scan];
+
+                    for (k = 0; k < numcoeff; k++)
                     {
-                      coef_ctr += runarr[k]+1;
+                      if (levarr[k] != 0)
+                      {
+                        pos_scan_4x4 += (runarr[k] << 1);
+
+                        i0 = *pos_scan_4x4++;
+                        j0 = *pos_scan_4x4++;
 
-                      i0 = pos_scan4x4[coef_ctr][0];
-                      j0 = pos_scan4x4[coef_ctr][1];
+                        // inverse quant for 4x4 transform only
+                        currMB->cbp_blk |= (int64) 1 << ((j<<2) + i);
 
-                      // inverse quant for 4x4 transform only
-                      currMB->cbp_blk |= (int64) 1 << ((j<<2) + i);
-                      img->cof[0][(j<<2) + j0][(i<<2) + i0]= rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per, 4);
+                        img->cof[0][(j<<2) + j0][(i<<2) + i0]= rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per, 4);
+                        img->fcf[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
+                      }
                     }
                   }
                 }
               }
-            }
-            else
-            {
-              for (j=block_y; j < block_y+2; j++)
+              else
               {
-                for (i=block_x; i < block_x+2; i++)
-                {               
-                  img->nz_coeff[mb_nr][i][j] = 0;
+                for (j=block_y; j < block_y + 2; j++)
+                {
+                  memset(&img->nz_coeff[mb_nr][0][j][block_x], 0, 2 * sizeof(int));
                 }
               }
             }
           }
         }
+        else
+        {
+          memset(&img->nz_coeff[mb_nr][0][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
+        }
       }
       else // 8x8 transform
       {
-        int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
-
-        for (block_y=0; block_y < 4; block_y += 2) /* all modes */
+        if (cbp)
         {
-          for (block_x=0; block_x < 4; block_x += 2)
-          {
-            b8 = 2*(block_y>>1) + (block_x>>1);
+          int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
 
-            if (cbp & (1<<b8))  /* are there any coeff in current block at all */
+          for (block_y=0; block_y < 4; block_y += 2) /* all modes */
+          {
+            for (block_x=0; block_x < 4; block_x += 2)
             {
-              for (j=block_y; j < block_y+2; j++)
+              b8 = 2*(block_y>>1) + (block_x>>1);
+
+              if (cbp & (1<<b8))  /* are there any coeff in current block at all */
               {
-                for (i=block_x; i < block_x+2; i++)
+                for (j=block_y; j < block_y+2; j++)
                 {
-                  readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
+                  for (i=block_x; i < block_x+2; i++)
+                  {
+                    readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
 
-                  coef_ctr = start_scan - 1;
+                    coef_ctr = start_scan - 1;
 
-                  for (k = 0; k < numcoeff; k++)
-                  {
-                    if (levarr[k] != 0)
+                    for (k = 0; k < numcoeff; k++)
                     {
-                      coef_ctr += runarr[k]+1;
+                      if (levarr[k] != 0)
+                      {
+                        coef_ctr += runarr[k]+1;
 
-                      // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s
-                      //as containing coefficients
-                      currMB->cbp_blk  |= 51 << ((block_y<<2) + block_x);
+                        // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s
+                        //as containing coefficients
+                        currMB->cbp_blk  |= 51 << ((block_y<<2) + block_x);
 
-                      b4 = (coef_ctr << 2) + 2*(j - block_y)+(i - block_x);
+                        b4 = (coef_ctr << 2) + 2*(j - block_y)+(i - block_x);
 
-                      i0 = pos_scan8x8[b4][0];
-                      j0 = pos_scan8x8[b4][1];
+                        i0 = pos_scan8x8[b4][0];
+                        j0 = pos_scan8x8[b4][1];
 
-                      img->m7[0][block_y*4 +j0][block_x*4 +i0] = rshift_rnd_sf((levarr[k] * InvLevelScale8x8[j0][i0])<<qp_per, 6); // dequantization
-                    }
-                  }//else (!currMB->luma_transform_size_8x8_flag)
+                        img->mb_rres[0][block_y*4 +j0][block_x*4 +i0] = rshift_rnd_sf((levarr[k] * InvLevelScale8x8[j0][i0])<<qp_per, 6); // dequantization
+                      }
+                    }//else (!currMB->luma_transform_size_8x8_flag)
+                  }
                 }
               }
-            }
-            else
-            {
-              for (j=block_y; j < block_y+2; j++)
+              else
               {
-                for (i=block_x; i < block_x+2; i++)
-                {               
-                  img->nz_coeff[mb_nr][i][j] = 0;
+                for (j=block_y; j < block_y+2; j++)
+                {
+                  memset(&img->nz_coeff[mb_nr][0][j][block_x], 0, 2 * sizeof(int));
                 }
               }
             }
           }
         }
+        else
+        {
+          memset(&img->nz_coeff[mb_nr][0][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
+        }
       }
     }
     else // if (!lossless_qpprime)
@@ -3093,6 +3225,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
                       currMB->cbp_blk      |= (int64) 1 << ((j<<2) + i);
                       img->cof[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
+                      img->fcf[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
                     }
                   }
                 }
@@ -3114,14 +3247,14 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                       iz=pos_scan8x8[coef_ctr*4+b4][0];
                       jz=pos_scan8x8[coef_ctr*4+b4][1];
 
-                      img->m7[0][block_y*4 +jz][block_x*4 +iz] = levarr[k];
+                      img->mb_rres[0][block_y*4 +jz][block_x*4 +iz] = levarr[k];
                     }
                   }
                 }//else (!currMB->luma_transform_size_8x8_flag)
               }
               else
               {
-                img->nz_coeff[mb_nr][i][j] = 0;
+                img->nz_coeff[mb_nr][0][j][i] = 0;
               }
             }
           }
@@ -3133,14 +3266,13 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   {
     //======= Other Modes & CABAC ========
     //------------------------------------          
-
     if(currMB->luma_transform_size_8x8_flag)
     {
       for (block_y=0; block_y < 4; block_y += 2) /* all modes */
       {
         for (b8 = block_y; b8 < block_y + 2; b8 += 1)
         {      
-          readLumaCoeff8x8_CABAC(currMB, PLANE_Y, img, b8); //======= 8x8 trannsform size & CABAC ========
+          readLumaCoeff8x8_CABAC(img, currMB, PLANE_Y, b8); //======= 8x8 trannsform size & CABAC ========
         }
       }
     }
@@ -3148,61 +3280,66 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     {
       if(!lossless_qpprime)
       {
-        start_scan = IS_NEWINTRA (currMB)? 1 : 0;              
-        img->is_intra_block = intra;
-        currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
-
-        for (block_y=0; block_y < 4; block_y += 2) /* all modes */
+        if (cbp)
         {
-          for (block_x=0; block_x < 4; block_x += 2)
+          start_scan = IS_NEWINTRA (currMB)? 1 : 0;          
+
+          img->is_intra_block = intra;
+          currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
+
+          for (block_y=0; block_y < 4; block_y += 2) /* all modes */
           {
-            b8 = 2*(block_y>>1) + (block_x>>1);
-            
-            if (cbp & (1<<b8))  // are there any coeff in current block at all
+            for (block_x=0; block_x < 4; block_x += 2)
             {
-              for (j = (block_y<<2); j < (block_y<<2) + 8; j += 4)
-              {
-                img->subblock_y = (j>>2); // position for coeff_count ctx
+              b8 = 2*(block_y>>1) + (block_x>>1);
 
-                for (i = block_x; i < block_x + 2; i++)
+              if (cbp & (1<<b8))  // are there any coeff in current block at all
+              {
+                for (j = (block_y<<2); j < (block_y<<2) + 8; j += 4)
                 {
-                  img->subblock_x = i; // position for coeff_count ctx
+                  img->subblock_y = (j>>2); // position for coeff_count ctx
 
-                  coef_ctr = start_scan - 1;
-                  level    = 1;
-
-                  for(k=start_scan;(k<17) && (level!=0);k++)
+                  for (i = block_x; i < block_x + 2; i++)
                   {
-                    /*
-                    * make distinction between INTRA and INTER coded
-                    * luminance coefficients
-                    */
-                    currSE.type = (img->is_intra_block 
-                      ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
-                      : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));                                      
+                    img->subblock_x = i; // position for coeff_count ctx
+                    pos_scan_4x4 = pos_scan4x4[start_scan];
 
-#if TRACE
-                    sprintf(currSE.tracestring, "Luma sng ");
-#endif
-                    dP = &(currSlice->partArr[partMap[currSE.type]]);
+                    level    = 1;
 
-                    if (dP->bitstream->ei_flag)  
-                      currSE.mapping = linfo_levrun_inter;
-                    else                                                     
-                      currSE.reading = readRunLevel_CABAC;
+                    for(k=start_scan;(k<17) && (level!=0);k++)
+                    {
+                      /*
+                      * make distinction between INTRA and INTER coded
+                      * luminance coefficients
+                      */
+                      currSE.type = (img->is_intra_block 
+                        ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
+                        : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));                                      
 
-                    dP->readSyntaxElement(&currSE,img,dP);
-                    level = currSE.value1;
+#if TRACE
+                      sprintf(currSE.tracestring, "Luma sng ");
+#endif
+                      dP = &(currSlice->partArr[partMap[currSE.type]]);
 
-                    if (level != 0)    /* leave if len=1 */
-                    {
-                      coef_ctr += currSE.value2 + 1;
+                      if (dP->bitstream->ei_flag)  
+                        currSE.mapping = linfo_levrun_inter;
+                      else                                                     
+                        currSE.reading = readRunLevel_CABAC;
 
-                      i0=pos_scan4x4[coef_ctr][0];
-                      j0=pos_scan4x4[coef_ctr][1];
+                      dP->readSyntaxElement(&currSE,img,dP);
+                      level = currSE.value1;
 
-                      currMB->cbp_blk |= (int64)1 << (j + i) ;
-                      img->cof[0][j + j0][(i<<2) + i0]= rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per, 4);
+                      if (level != 0)    /* leave if len=1 */
+                      {
+                        pos_scan_4x4 += 2 * currSE.value2;
+                        
+                        i0 = *pos_scan_4x4++;
+                        j0 = *pos_scan_4x4++;
+
+                        currMB->cbp_blk |= (int64)1 << (j + i) ;
+                        img->cof[0][j + j0][(i<<2) + i0]= rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per, 4);
+                        img->fcf[0][j + j0][(i<<2) + i0]= level;
+                      }
                     }
                   }
                 }
@@ -3259,8 +3396,6 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
                     dP->readSyntaxElement(&currSE,img,dP);
                     level = currSE.value1;
-                    //run   = currSE.value2;
-                    //len   = currSE.len;
 
                     if (level != 0)    /* leave if len=1 */
                     {
@@ -3271,6 +3406,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
                       currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ;
                       img->cof[0][(j<<2) + j0][(i<<2) + i0] = level;
+                      img->fcf[0][(j<<2) + j0][(i<<2) + i0] = level;
                     }
                   }
                 }
@@ -3287,6 +3423,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     for (uv = 0; uv < 2; uv++ )
     {
       memset(&img->cof[uv + 1][0][0], 0, MB_PIXELS * sizeof(int));
+      memset(&img->fcf[uv + 1][0][0], 0, MB_PIXELS * sizeof(int));
 
       /*----------------------16x16DC Luma_Add----------------------*/
       if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes       
@@ -3312,7 +3449,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
               i0=pos_scan4x4[coef_ctr][0];
               j0=pos_scan4x4[coef_ctr][1];
-              img->cof[uv + 1][j0<<2][i0<<2]=levarr[k];// add new intra DC coeff
+              img->cof[uv + 1][j0<<2][i0<<2] = levarr[k];// add new intra DC coeff
+              img->fcf[uv + 1][j0<<2][i0<<2] = levarr[k];// add new intra DC coeff
             } //if leavarr[k]
           } //k loop
         } //UVLC
@@ -3365,30 +3503,30 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
               i0=pos_scan4x4[coef_ctr][0];
               j0=pos_scan4x4[coef_ctr][1];
-              img->cof[uv + 1][j0<<2][i0<<2]=level;
+              img->cof[uv + 1][j0<<2][i0<<2] = level;
+              img->fcf[uv + 1][j0<<2][i0<<2] = level;
             }                        
           } //k loop
         } // else UVLC
 
         if(!lossless_qpprime)
         {
-          itrans_2((ColorPlane) (uv + 1), img); // transform new intra DC
+          itrans_2(img, currMB, (ColorPlane) (uv + 1)); // transform new intra DC
         }
 
       } //IS_NEWINTRA
 
-      currMB->qp = img->qp;
-      set_chroma_qp(currMB);
+      update_qp(img, currMB, img->qp);
 
-      qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
-      qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
+      qp_per    = qp_per_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
+      qp_rem    = qp_rem_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
 
       //init constants for every chroma qp offset
-      qp_per_uv[uv] = (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale)/6;
-      qp_rem_uv[uv] = (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale)%6;
+      qp_per_uv[uv] = qp_per_matrix[ (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale) ];
+      qp_rem_uv[uv] = qp_rem_matrix[ (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale) ];
 
-      InvLevelScale4x4 = intra? InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]] : InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]];
-      InvLevelScale8x8 = intra? InvLevelScale8x8Chroma_Intra[uv][qp_rem_uv[uv]] : InvLevelScale8x8Chroma_Intra[uv][qp_rem_uv[uv]];
+      InvLevelScale4x4 = intra? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
+      InvLevelScale8x8 = intra? InvLevelScale8x8_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale8x8_Inter[uv + 1][qp_rem_uv[uv]];
 
 
       // luma_add coefficients
@@ -3433,7 +3571,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
                           // inverse quant for 4x4 transform only
                           currMB->cbp_blk_CbCr[uv] |= (int64) 1 << ((j<<2) + i);
-                          img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0]= rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv],4);          
+                          img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv],4);          
+                          img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
                         } //levarr[k] != 0
                       }//k loop
                     } //4x4
@@ -3454,7 +3593,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
                           iz = pos_scan8x8[(coef_ctr << 2) + b4][0];
                           jz = pos_scan8x8[(coef_ctr << 2) + b4][1];
-                          img->m7[uv+1][block_y*4 +jz][block_x*4 +iz] = rshift_rnd_sf((levarr[k]*InvLevelScale8x8[jz][iz])<<qp_per_uv[uv], 6); // dequantization 444_TEMP_NOTE 
+                          img->mb_rres[uv+1][block_y*4 +jz][block_x*4 +iz] = rshift_rnd_sf((levarr[k]*InvLevelScale8x8[jz][iz])<<qp_per_uv[uv], 6); // dequantization 444_TEMP_NOTE 
                         } //if levarr
                       }//8x8
                     }//k loop
@@ -3473,6 +3612,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                           j0=pos_scan4x4[coef_ctr][1];
                           currMB->cbp_blk_CbCr[uv] |= (int64) 1 << ((j<<2) + i);
                           img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
+                          img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
                         } //levarr[k]
                       } //k loop
                     } //4x4
@@ -3494,7 +3634,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                           iz=pos_scan8x8[coef_ctr*4+b4][0];
                           jz=pos_scan8x8[coef_ctr*4+b4][1];
 
-                          img->m7[uv+1][block_y*4 +jz][block_x*4 +iz] = levarr[k];
+                          img->mb_rres[uv+1][block_y*4 +jz][block_x*4 +iz] = levarr[k];
                         } //levarr[k]
                       } //k loop
                     } //8x8
@@ -3502,7 +3642,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                 } //if (cbp & (1<<b8))                                
                 else //!(cbp & (1<<b8))
                 {
-                  img->nz_coeff[mb_nr][i][(4 << uv) +j] = 0;
+                  img->nz_coeff[mb_nr][uv + 1][j][i] = 0;
                 } //!(cbp & (1<<b8))
               } //i=block_x
             } //j=block_y
@@ -3511,7 +3651,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
           {            
             if(currMB->luma_transform_size_8x8_flag) 
             {
-              readLumaCoeff8x8_CABAC(currMB, (ColorPlane) (PLANE_U + uv), img, b8); //======= 8x8 trannsform size & CABAC ========
+              readLumaCoeff8x8_CABAC(img, currMB, (ColorPlane) (PLANE_U + uv), b8); //======= 8x8 trannsform size & CABAC ========
             }
             else //4x4
             {              
@@ -3581,6 +3721,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                           j0=pos_scan4x4[coef_ctr][1];
                           currMB->cbp_blk_CbCr[uv] |= (int64)1 << ((j<<2) + i) ;
                           img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per_uv[uv], 4); //444_TEMP_NOTE
+                          img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
                         }//level != 0
                       } //k loop
                     }//!lossless
@@ -3631,6 +3772,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                           j0=pos_scan4x4[coef_ctr][1];
                           currMB->cbp_blk_CbCr[uv] |= (int64)1 << ((j<<2) + i);
                           img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
+                          img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
                         } //level != 0
                       }//k loop
                     } //lossless                    
@@ -3647,6 +3789,9 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
   {
     memset(&img->cof[1][0][0], 0, MB_PIXELS * sizeof(int));
     memset(&img->cof[2][0][0], 0, MB_PIXELS * sizeof(int));
+    memset(&img->fcf[1][0][0], 0, MB_PIXELS * sizeof(int));
+    memset(&img->fcf[2][0][0], 0, MB_PIXELS * sizeof(int));
+
 
     //========================== CHROMA DC ============================
     //-----------------------------------------------------------------
@@ -3654,15 +3799,14 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     if(cbp>15)
     {
       if (dec_picture->chroma_format_idc == YUV420)
-      {
-        int (*InvLevelScale4x4Chroma)[4];
+      {    
         for (ll=0;ll<3;ll+=2)
         {
           uv = ll>>1;          
 
           if (active_pps->entropy_coding_mode_flag == UVLC)
           {
-            InvLevelScale4x4Chroma = intra ? InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]] : InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]];
+            InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
             //===================== CHROMA DC YUV420 ======================
             memset(&img->cofu[0], 0, 4 *sizeof(int));
 
@@ -3681,7 +3825,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
           }
           else
           {
-            InvLevelScale4x4Chroma = intra ? InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]] : InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]];
+            InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
             //===================== CHROMA DC YUV420 ======================
             memset(&img->cofu[0], 0, 4 *sizeof(int));
 
@@ -3699,7 +3843,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
             else
               currSE.reading = readRunLevel_CABAC;
 
-            for(k = 0; (k < (img->num_cdc_coeff+1))&&(level!=0);k++)
+            for(k = 0; (k < (img->num_cdc_coeff + 1))&&(level!=0);k++)
             {
 #if TRACE
               snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x2 DC Chroma ");
@@ -3707,8 +3851,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
               dP->readSyntaxElement(&currSE,img,dP);
               level = currSE.value1;
-              //run = currSE.value2;
-              //len = currSE.len;
+
               if (level != 0)
               {
                 currMB->cbp_blk |= 0xf0000 << (ll<<1) ;
@@ -3730,23 +3873,31 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
 
           if (smb || lossless_qpprime) // check to see if MB type is SPred or SIntra4x4
           {                
-            img->cof[uv + 1][0][0]=img->cofu[0];
-            img->cof[uv + 1][0][4]=img->cofu[1];
-            img->cof[uv + 1][4][0]=img->cofu[2];
-            img->cof[uv + 1][4][4]=img->cofu[3];
+            img->cof[uv + 1][0][0] = img->cofu[0];
+            img->cof[uv + 1][4][0] = img->cofu[1];
+            img->cof[uv + 1][0][4] = img->cofu[2];
+            img->cof[uv + 1][4][4] = img->cofu[3];
+            img->fcf[uv + 1][0][0] = img->cofu[0];
+            img->fcf[uv + 1][4][0] = img->cofu[1];
+            img->fcf[uv + 1][0][4] = img->cofu[2];
+            img->fcf[uv + 1][4][4] = img->cofu[3];
           }
           else
           {
             ihadamard2x2(img->cofu, temp);
+            img->fcf[uv + 1][0][0] = temp[0];
+            img->fcf[uv + 1][0][4] = temp[1];
+            img->fcf[uv + 1][4][0] = temp[2];
+            img->fcf[uv + 1][4][4] = temp[3];
 
             for (i=0;i<img->num_cdc_coeff;i++)
             {
-              temp[i]= (((temp[i] * InvLevelScale4x4Chroma[0][0])<<qp_per_uv[uv])>>5);
+              temp[i]= (((temp[i] * InvLevelScale4x4[0][0])<<qp_per_uv[uv])>>5);
             }
-            img->cof[uv + 1][0][0]=temp[0];
-            img->cof[uv + 1][0][4]=temp[1];
-            img->cof[uv + 1][4][0]=temp[2];
-            img->cof[uv + 1][4][4]=temp[3];
+            img->cof[uv + 1][0][0] = temp[0];
+            img->cof[uv + 1][0][4] = temp[1];
+            img->cof[uv + 1][4][0] = temp[2];
+            img->cof[uv + 1][4][4] = temp[3];
           }          
         }
       }
@@ -3754,12 +3905,19 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
       {
         for (ll=0;ll<3;ll+=2)
         {
+          int (*InvLevelScale4x4)[4] = NULL;
           uv = ll>>1;
           {
+            int (*imgcof)[16] = img->cof[uv + 1];
             int m3[2][4] = {{0,0,0,0},{0,0,0,0}};
             int m4[2][4] = {{0,0,0,0},{0,0,0,0}};
-            int qp_per_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)/6;       //for YUV422 only
-            int qp_rem_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)%6;       //for YUV422 only
+            int qp_per_uv_dc = qp_per_matrix[ (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale) ];       //for YUV422 only
+            int qp_rem_uv_dc = qp_rem_matrix[ (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale) ];       //for YUV422 only
+            if (intra)
+              InvLevelScale4x4 = InvLevelScale4x4_Intra[uv + 1][qp_rem_uv_dc];
+            else 
+              InvLevelScale4x4 = InvLevelScale4x4_Inter[uv + 1][qp_rem_uv_dc];
+
 
             //===================== CHROMA DC YUV422 ======================
             if (active_pps->entropy_coding_mode_flag == UVLC)
@@ -3772,7 +3930,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                 if (levarr[k] != 0)
                 {
                   currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2);
-                  coef_ctr=coef_ctr+runarr[k]+1;
+                  coef_ctr += runarr[k]+1;
                   i0 = SCAN_YUV422[coef_ctr][0];
                   j0 = SCAN_YUV422[coef_ctr][1];
 
@@ -3802,9 +3960,9 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                   currSE.reading = readRunLevel_CABAC;
 
                 dP->readSyntaxElement(&currSE,img,dP);
+
                 level = currSE.value1;
-                //run = currSE.value2;
-                //len = currSE.len;
+
                 if (level != 0)
                 {
                   currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2) ;
@@ -3830,63 +3988,40 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
               m4[1][1] = m3[0][1] - m3[1][1];
               m4[1][2] = m3[0][2] - m3[1][2];
               m4[1][3] = m3[0][3] - m3[1][3];
+
+              for (i = 0; i < 2; i++)
+              {
+                m6[0] = m4[i][0] + m4[i][2];
+                m6[1] = m4[i][0] - m4[i][2];
+                m6[2] = m4[i][1] - m4[i][3];
+                m6[3] = m4[i][1] + m4[i][3];
+
+                imgcof[ 0][i<<2] = m6[0] + m6[3];
+                imgcof[ 4][i<<2] = m6[1] + m6[2];
+                imgcof[ 8][i<<2] = m6[1] - m6[2];
+                imgcof[12][i<<2] = m6[0] - m6[3];
+              }//for (i=0;i<2;i++)
             }
             else
             {
-              for(i=0;i<2;i++)
-                for(j=0;j<4;j++)
-                  img->cof[uv + 1][j<<2][i<<2]=m3[i][j];
-            }
-
-            // vertical
-            for (i=0;i<2 && !lossless_qpprime;i++)
-            {
-              // This is not right with the 16x16 mtr structure. Needs revisit... AMT
-              int (*imgcof)[16] = img->cof[uv + 1];
-              for (j=0; j < 4;j++)    //TODO: remove m5 with m4
-                m5[j]=m4[i][j];
-
-              m6[0]=m5[0]+m5[2];
-              m6[1]=m5[0]-m5[2];
-              m6[2]=m5[1]-m5[3];
-              m6[3]=m5[1]+m5[3];
-
-
-              if(qp_per_uv_dc<4)
+              for(j=0;j<4;j++)
               {
-                if(intra == 1)
-                {
-                  imgcof[ 0][i<<2] = ((((m6[0]+m6[3])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[ 4][i<<2] = ((((m6[1]+m6[2])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[ 8][i<<2] = ((((m6[1]-m6[2])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[12][i<<2] = ((((m6[0]-m6[3])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                }
-                else
+                for(i=0;i<2;i++)                
                 {
-                  imgcof[ 0][i<<2] = ((((m6[0]+m6[3])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[ 4][i<<2] = ((((m6[1]+m6[2])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[ 8][i<<2] = ((((m6[1]-m6[2])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
-                  imgcof[12][i<<2] = ((((m6[0]-m6[3])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
+                  img->cof[uv + 1][j<<2][i<<2] = m3[i][j];
+                  img->fcf[uv + 1][j<<2][i<<2] = m3[i][j];
                 }
               }
-              else
+            }
+
+
+            for(j = 0;j < img->mb_cr_size_y; j += BLOCK_SIZE)
+            {
+              for(i=0;i < img->mb_cr_size_x;i+=BLOCK_SIZE)
               {
-                if(intra == 1)
-                {
-                  imgcof[ 0][i<<2] = ((((m6[0]+m6[3])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[ 4][i<<2] = ((((m6[1]+m6[2])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[ 8][i<<2] = ((((m6[1]-m6[2])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[12][i<<2] = ((((m6[0]-m6[3])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                }
-                else
-                {
-                  imgcof[ 0][i<<2] = ((((m6[0]+m6[3])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[ 4][i<<2] = ((((m6[1]+m6[2])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[ 8][i<<2] = ((((m6[1]-m6[2])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                  imgcof[12][i<<2] = ((((m6[0]-m6[3])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
-                }
+                imgcof[j][i] = rshift_rnd_sf((imgcof[j][i] * InvLevelScale4x4[0][0]) << qp_per_uv_dc, 6);
               }
-            }//for (i=0;i<2;i++)
+            }
           }
         }//for (ll=0;ll<3;ll+=2)
       }//else if (dec_picture->chroma_format_idc == YUV422)
@@ -3896,30 +4031,28 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
     //-----------------------------------------------------------------
     // chroma AC coeff, all zero fram start_scan
     if (cbp<=31)
-      for (i=0; i < 4; i++)
-        memset(&img->nz_coeff [mb_nr ][i][4], 0, img->num_blk8x8_uv * sizeof(int));
+    {
+      if (active_pps->entropy_coding_mode_flag == UVLC)
+        memset(&img->nz_coeff [mb_nr ][1][0][0], 0, 2 * BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
+    }
     else
     {
-      int (*InvLevelScale4x4Chroma)[4];
-
       if (active_pps->entropy_coding_mode_flag == UVLC)
       {
         if(!lossless_qpprime)
         {
           for (b8=0; b8 < img->num_blk8x8_uv; b8++)
           {
-            int uvc = (b8 > ((img->num_uv_blocks) - 1 ));
-            InvLevelScale4x4Chroma = intra ? InvLevelScale4x4Chroma_Intra[uvc][qp_rem_uv[uvc]] : InvLevelScale4x4Chroma_Inter[uvc][qp_rem_uv[uvc]];
-
-            img->is_v_block = uv = uvc;
+            img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
+            InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
 
             for (b4=0; b4 < 4; b4++)
             {
               i = cofuv_blk_x[yuv][b8][b4];
               j = cofuv_blk_y[yuv][b8][b4];
 
-              readCoeff4x4_CAVLC(currMB, img, CHROMA_AC, i + 2*uvc, j + 4, levarr, runarr, &numcoeff);
-              coef_ctr=0;
+              readCoeff4x4_CAVLC(currMB, img, CHROMA_AC, i + 2*uv, j + 4, levarr, runarr, &numcoeff);
+              coef_ctr = 0;
 
               for(k = 0; k < numcoeff;k++)
               {
@@ -3931,7 +4064,8 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                   i0=pos_scan4x4[coef_ctr][0];
                   j0=pos_scan4x4[coef_ctr][1];
 
-                  img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((levarr[k]*InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4);
+                  img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv], 4);
+                  img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
                 }
               }
             }
@@ -3941,9 +4075,7 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
         {
           for (b8=0; b8 < img->num_blk8x8_uv; b8++)
           {
-            int uvc = (b8 > ((img->num_uv_blocks) - 1 ));
-
-            img->is_v_block = uv = uvc;
+            img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
 
             for (b4=0; b4 < 4; b4++)
             {
@@ -3961,10 +4093,11 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                   currMB->cbp_blk |= ((int64) 1) << cbp_blk_chroma[b8][b4];
                   coef_ctr += runarr[k] + 1;
 
-                  i0=pos_scan4x4[coef_ctr][0];
-                  j0=pos_scan4x4[coef_ctr][1];
+                  i0 = pos_scan4x4[coef_ctr][0];
+                  j0 = pos_scan4x4[coef_ctr][1];
 
                   img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
+                  img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
                 }
               }
             }
@@ -3973,9 +4106,10 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
       }
       else
       {
-        currSE.context      = CHROMA_AC;
-        currSE.type         = (IS_INTRA(currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER);
         img->is_intra_block =  IS_INTRA(currMB);
+        currSE.context      = CHROMA_AC;
+        currSE.type         = (img->is_intra_block ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER);
+
         dP = &(currSlice->partArr[partMap[currSE.type]]);
 
         if (dP->bitstream->ei_flag)
@@ -3987,12 +4121,10 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
         {          
           for (b8=0; b8 < img->num_blk8x8_uv; b8++)
           {
-            int uvc = (b8 > ((img->num_uv_blocks) - 1 ));
-            InvLevelScale4x4Chroma = intra ? InvLevelScale4x4Chroma_Intra[uvc][qp_rem_uv[uvc]] : InvLevelScale4x4Chroma_Inter[uvc][qp_rem_uv[uvc]];
-
-            img->is_v_block = uv = uvc;
+            img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
+            InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
 
-            for (b4=0; b4 < 4; b4++)
+            for (b4 = 0; b4 < 4; b4++)
             {
               i = cofuv_blk_x[yuv][b8][b4];
               j = cofuv_blk_y[yuv][b8][b4];
@@ -4000,11 +4132,10 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
               img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2;
               img->subblock_x = subblk_offset_x[yuv][b8][b4]>>2;
 
-              coef_ctr=0;
+              pos_scan_4x4 = pos_scan4x4[1];
               level=1;
 
-
-              for(k=0;(k<16)&&(level!=0);k++)
+              for(k = 0; (k < 16) && (level != 0);k++)
               {
 #if TRACE
                 snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma ");
@@ -4016,12 +4147,13 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                 if (level != 0)
                 {
                   currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
-                  coef_ctr += (currSE.value2 + 1);
-
-                  i0=pos_scan4x4[coef_ctr][0];
-                  j0=pos_scan4x4[coef_ctr][1];
+                  pos_scan_4x4 += (currSE.value2 << 1);
+                  
+                  i0 = *pos_scan_4x4++;
+                  j0 = *pos_scan_4x4++;
 
-                  img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((level * InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4);
+                  img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((level * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv], 4);
+                  img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
                 }
               } //for(k=0;(k<16)&&(level!=0);k++)
             }
@@ -4031,16 +4163,14 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
         {
           for (b8=0; b8 < img->num_blk8x8_uv; b8++)
           {
-            int uvc = (b8 > ((img->num_uv_blocks) - 1 ));
-
-            img->is_v_block = uv = uvc;
+            img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
 
             for (b4=0; b4 < 4; b4++)
             {
               i = cofuv_blk_x[yuv][b8][b4];
               j = cofuv_blk_y[yuv][b8][b4];
 
-              coef_ctr=0;
+              pos_scan_4x4 = pos_scan4x4[1];
               level=1;
 
               img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2;
@@ -4057,12 +4187,13 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
                 if (level != 0)
                 {
                   currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
-                  coef_ctr += (currSE.value2 + 1);
-
-                  i0=pos_scan4x4[coef_ctr][0];
-                  j0=pos_scan4x4[coef_ctr][1];
+                  pos_scan_4x4 += (currSE.value2 << 1);
+                  
+                  i0 = *pos_scan_4x4++;
+                  j0 = *pos_scan_4x4++;
 
                   img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
+                  img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
                 }
               } 
             }
@@ -4084,48 +4215,60 @@ void readCBPandCoeffsFromNAL(Macroblock *currMB, ImageParameters *img)
  ************************************************************************
  */
 
-void decode_ipcm_mb(Macroblock *currMB, ImageParameters *img)
+void decode_ipcm_mb(ImageParameters *img, Macroblock *currMB)
 {
-  int i,j;
+  int i, j, k;
   int mb_nr = img->current_mb_nr;
 
   //Copy coefficients to decoded picture buffer
   //IPCM coefficients are stored in img->cof which is set in function readIPCMcoeffsFromNAL()
 
-  for(i=0;i<16;i++)
-    for(j=0;j<16;j++)
+  for(i = 0; i < MB_BLOCK_SIZE; i++)
+  {
+    for(j = 0;j < MB_BLOCK_SIZE ; j++)
+    {
       dec_picture->imgY[img->pix_y+i][img->pix_x+j] = (imgpel) img->cof[0][i][j];
+    }
+  }
 
   if ((dec_picture->chroma_format_idc != YUV400) && !IS_INDEPENDENT(img))
   {
-    for(i=0;i<img->mb_cr_size_y;i++)
-      for(j=0;j<img->mb_cr_size_x;j++)
-        dec_picture->imgUV[0][img->pix_c_y+i][img->pix_c_x+j] = (imgpel) img->cof[1][i][j];  
-
-    for(i=0;i<img->mb_cr_size_y;i++)
-      for(j=0;j<img->mb_cr_size_x;j++)
-        dec_picture->imgUV[1][img->pix_c_y+i][img->pix_c_x+j] = (imgpel) img->cof[2][i][j];  
+    for (k = 0; k < 2; k++)
+    {
+      for(i = 0; i < img->mb_cr_size_y; i++)
+      {
+        for(j = 0;j < img->mb_cr_size_x; j++)
+        {
+          dec_picture->imgUV[k][img->pix_c_y+i][img->pix_c_x+j] = (imgpel) img->cof[k + 1][i][j];  
+        }
+      }
+    }
   }
 
   // for deblocking filter
-  currMB->qp=0;
-  set_chroma_qp(currMB);
+  update_qp(img, currMB, 0);
 
   // for CAVLC: Set the nz_coeff to 16.
-  // These parameters are to be used in CAVLC decoding of neighbour blocks
-  for(i=0;i<4;i++)
-    for (j=0;j<(4 + img->num_blk8x8_uv);j++)
-      img->nz_coeff[mb_nr][i][j]=16;
-
+  // These parameters are to be used in CAVLC decoding of neighbour blocks  
+  for (k = 0; k < 3; k++)
+  {
+    for (j = 0; j < BLOCK_SIZE; j++)
+    {
+      for(i = 0; i < BLOCK_SIZE; i++)
+      {
+        img->nz_coeff[mb_nr][k][j][i] = 16;
+      }
+    }
+  }
 
   // for CABAC decoding of MB skip flag
   currMB->skip_flag = 0;
 
   //for deblocking filter CABAC
-  currMB->cbp_blk=0xFFFF;
+  currMB->cbp_blk = 0xFFFF;
 
   //For CABAC decoding of Dquant
-  last_dquant=0;
+  last_dquant = 0;
 }
 
 /*!
@@ -4135,93 +4278,86 @@ void decode_ipcm_mb(Macroblock *currMB, ImageParameters *img)
  ************************************************************************
  */
 
-int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
+int decode_one_macroblock(ImageParameters *img, Macroblock *currMB, StorablePicture *dec_picture)
 {
   int i=0,j=0,k,l,ii=0,jj=0, j4=0,i4=0, j6;  
   int refList;
   int uv, hv;
   int ioff,joff;
   int block8x8;   // needed for ABT
-    int j_pos, i_pos;
-  
+  int j_pos, i_pos;
+
   static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
   int mb_nr     = img->current_mb_nr;
-  
+
   short ref_idx;
   int mv_mode, pred_dir; // = currMB->ref_frame;  
-  
-    int block_size_x, block_size_y;
-  
+
+  int block_size_x, block_size_y;
+
   int mv_scale;
   static imgpel **curComp;
   static imgpel (*mpr) [16];
   static imgpel *cur_line;
   static int    *cur_m7;
-  
+
   int smb = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
   int list_offset;
-  
+
   char l0_rFrame = -1, l1_rFrame = -1;
-  
+
   short pmvl0[2]={0,0}, pmvl1[2]={0,0};
-  
+
   int direct_pdir=-1;
-  
+
   int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
-  
-  static byte  **    moving_block;
-  static short ****  co_located_mv;
-  static char  ***   co_located_ref_idx;
-  static int64 ***   co_located_ref_id;
-  
+
+  static MotionParams *colocated;
+
   int need_4x4_transform = (!currMB->luma_transform_size_8x8_flag);
   int yuv = dec_picture->chroma_format_idc - 1;
 
   //For residual DPCM
   Boolean lossless_qpprime = (Boolean) (((img->qp + img->bitdepth_luma_qp_scale) == 0) && (img->lossless_qpprime_flag == 1));  
   ipmode_DPCM = NO_INTRA_PMODE; 
-  
-  if(img->type==SP_SLICE && currMB->mb_type!=I16MB)
-    smb = 1;// modif ES added
-  
+
+  if (img->structure != FRAME || (img->MbaffFrameFlag && currMB->mb_field))
+    img->max_mb_vmv_r = img->max_vmv_r >> 1;
+  else
+    img->max_mb_vmv_r = img->max_vmv_r;
+
   if(currMB->mb_type == IPCM)
   {
     //copy readed data into imgY and set parameters
-    decode_ipcm_mb(currMB, img);
+    decode_ipcm_mb(img, currMB);
     return 0;
   }
-  
+
+  if (img->type==SP_SLICE && currMB->mb_type!=I16MB)
+    smb = 1;// modif ES added
+
   //////////////////////////
-  
+
   // find out the correct list offsets
   if (curr_mb_field)
   {
     if(mb_nr&0x01)
     {
       list_offset = 4; // top field mb
-      moving_block = Co_located->bottom_moving_block;
-      co_located_mv = Co_located->bottom_mv;
-      co_located_ref_idx = Co_located->bottom_ref_idx;
-      co_located_ref_id = Co_located->bottom_ref_pic_id;
+      colocated = &Co_located->bottom;
     }
     else
     {
       list_offset = 2; // bottom field mb
-      moving_block = Co_located->top_moving_block;
-      co_located_mv = Co_located->top_mv;
-      co_located_ref_idx = Co_located->top_ref_idx;
-      co_located_ref_id = Co_located->top_ref_pic_id;
+      colocated = &Co_located->top;
     }
   }
   else
   {
     list_offset = 0;  // no mb aff or frame mb
-    moving_block = Co_located->moving_block;
-    co_located_mv = Co_located->mv;
-    co_located_ref_idx = Co_located->ref_idx;
-    co_located_ref_id = Co_located->ref_pic_id;
+    colocated = &Co_located->frame;
   }
-  
+
   if (!img->MbaffFrameFlag)
   {
     for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++)
@@ -4263,18 +4399,18 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
       }
     }
   }
-  
+
   // luma decoding **************************************************
-  
+
   // get prediction for INTRA_MB_16x16
   if (IS_NEWINTRA (currMB))
   {
-    intrapred_luma_16x16(currMB, PLANE_Y, img, currMB->i16mode);
+    intrapred_luma_16x16(img, currMB, PLANE_Y, currMB->i16mode);
     ipmode_DPCM = currMB->i16mode; //For residual DPCM
     // =============== 4x4 itrans ================
     // -------------------------------------------
     iMBtrans4x4(PLANE_Y, img, smb);
-    
+
     // chroma decoding *******************************************************
     if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444)) 
     {
@@ -4291,25 +4427,25 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
       {
         i =  (decode_block_scan[k] & 3);
         j = ((decode_block_scan[k] >> 2) & 3);
-        
+
         ioff = (i << 2);
         joff = (j << 2);
         i4   = img->block_x + i;
         j4   = img->block_y + j;
         j_pos = j4 * BLOCK_SIZE;
         i_pos = i4 * BLOCK_SIZE;
-        
+
         // PREDICTION
         //===== INTRA PREDICTION =====
-        if (intrapred(currMB, PLANE_Y, img,ioff,joff,i4,j4) == SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */
+        if (intrapred(img, currMB, PLANE_Y, ioff,joff,i4,j4) == SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */
           return SEARCH_SYNC;                   /* bit error */
         // =============== 4x4 itrans ================
         // -------------------------------------------
-        itrans_4x4  ((ColorPlane) LumaComp, img, ioff, joff);      // use DCT transform and make 4x4 block m7 from prediction block mpr
-        
+        itrans_4x4  (img, (ColorPlane) LumaComp, ioff, joff);      // use DCT transform and make 4x4 block m7 from prediction block mpr
+
         for(jj=0;jj<BLOCK_SIZE;jj++)
         {
-          cur_m7 = &img->m7[0][jj + joff][ioff];
+          cur_m7 = &img->mb_rres[0][jj + joff][ioff];
           cur_line = &dec_picture->imgY[j_pos + jj][i_pos];
           for(ii=0;ii<BLOCK_SIZE;ii++)
           {
@@ -4318,7 +4454,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
         }
       }
     }
-    
+
     // chroma decoding *******************************************************
     if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444)) 
     {
@@ -4334,15 +4470,15 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
       //=========== 8x8 BLOCK TYPE ============
       ioff = 8 * (block8x8 & 0x01);
       joff = 8 * (block8x8 >> 1);
-      
+
       //PREDICTION
-      intrapred8x8(PLANE_Y, img, currMB, block8x8);
+      intrapred8x8(img, currMB, PLANE_Y, block8x8);
+
+      itrans_8x8(img, currMB, PLANE_Y, ioff,joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
 
-      itrans_8x8(PLANE_Y, img,ioff,joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
-      
       for(jj = joff; jj < joff + 8;jj++)
       {
-        cur_m7 = &img->m7[0][jj][ioff];
+        cur_m7 = &img->mb_rres[0][jj][ioff];
         cur_line = &dec_picture->imgY[img->pix_y + jj][img->pix_x + ioff];
 
         for(ii = 0; ii < 8; ii++)
@@ -4363,11 +4499,11 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
     block_size_y = MB_BLOCK_SIZE;
     i = 0;
     j = 0;
-    
+
     pred_dir = LIST_0;   
     perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
-    
-    mpr = img->mpr[LumaComp];
+
+    mpr = img->mb_pred[LumaComp];
     curComp = &dec_picture->imgY[img->pix_y];
     for(j = 0; j < img->mb_size[0][1]; j++)
     {                
@@ -4379,8 +4515,8 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
       for(uv=0;uv<2;uv++)
       {
         curComp = &dec_picture->imgUV[uv][img->pix_c_y]; 
-        
-        mpr = img->mpr[uv + 1];
+
+        mpr = img->mb_pred[uv + 1];
         for(jj = 0; jj < img->mb_size[1][1]; jj++)
           memcpy(&(curComp[jj][img->pix_c_x]), &(mpr[jj][0]), img->mb_size[1][0] * sizeof(imgpel));
       }
@@ -4392,32 +4528,32 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
     block_size_y = MB_BLOCK_SIZE;
     i = 0;
     j = 0;
-    
+
     pred_dir = currMB->b8pdir[0];   
     perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
-    iTransform(currMB, PLANE_Y, img, need_4x4_transform, smb);
+    iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
   }
   else if (currMB->mb_type == P16x8)
   {   
     block_size_x = MB_BLOCK_SIZE;
     block_size_y = 8;    
-    
+
     for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
     {
       i = 0;
       j = block8x8;      
-      
+
       pred_dir = currMB->b8pdir[block8x8];
       perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
     }
-    iTransform(currMB, PLANE_Y, img, need_4x4_transform, smb); 
+    iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb); 
   }
   else if (currMB->mb_type == P8x16)
   {   
-    
+
     block_size_x = 8;
     block_size_y = 16;
-    
+
     for (block8x8 = 0; block8x8 < 2; block8x8 ++)
     {
       i = block8x8<<1;
@@ -4426,7 +4562,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
       assert (pred_dir<=2);
       perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
     }
-    iTransform(currMB, PLANE_Y, img, need_4x4_transform, smb);
+    iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
   }
   else
   {
@@ -4434,7 +4570,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
     if (img->type==B_SLICE && img->direct_spatial_mv_pred_flag && (IS_DIRECT (currMB) ||
       (IS_P8x8(currMB) && !(currMB->b8mode[0] && currMB->b8mode[1] && currMB->b8mode[2] && currMB->b8mode[3]))))
       prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
-    
+
     for (block8x8=0; block8x8<4; block8x8++)
     {
       mv_mode  = currMB->b8mode[block8x8];
@@ -4499,73 +4635,73 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
 
             if (l0_rFrame >=0)
             {
-              if (!l0_rFrame  && ((!moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+              if (!l0_rFrame  && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
               {
-                dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-                dec_picture->mv  [LIST_0][j4][i4][1] = 0;
-                dec_picture->ref_idx[LIST_0][j4][i4] = 0;
+                dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+                dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
+                dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
               }
               else
               {
-                dec_picture->mv  [LIST_0][j4][i4][0] = pmvl0[0];
-                dec_picture->mv  [LIST_0][j4][i4][1] = pmvl0[1];
-                dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame;
+                dec_picture->motion.mv  [LIST_0][j4][i4][0] = pmvl0[0];
+                dec_picture->motion.mv  [LIST_0][j4][i4][1] = pmvl0[1];
+                dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
               }
             }
             else
             {
-              dec_picture->ref_idx[LIST_0][j4][i4] = -1;
-              dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-              dec_picture->mv  [LIST_0][j4][i4][1] = 0;
+              dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
+              dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+              dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
             }
 
             if (l1_rFrame >=0)
             {
-              if  (l1_rFrame==0 && ((!moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+              if  (l1_rFrame==0 && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
               {
 
-                dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-                dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-                dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
+                dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+                dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+                dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
 
               }
               else
               {
-                dec_picture->mv  [LIST_1][j4][i4][0] = pmvl1[0];
-                dec_picture->mv  [LIST_1][j4][i4][1] = pmvl1[1];
-                dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
+                dec_picture->motion.mv  [LIST_1][j4][i4][0] = pmvl1[0];
+                dec_picture->motion.mv  [LIST_1][j4][i4][1] = pmvl1[1];
+                dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
               }
             }
             else
             {
-              dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-              dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-              dec_picture->ref_idx[LIST_1][j4][i4] = -1;
+              dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+              dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+              dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
             }
 
             if (l0_rFrame < 0 && l1_rFrame < 0)
             {
-              dec_picture->ref_idx[LIST_0][j4][i4] = 0;
-              dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+              dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+              dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
             }
 
-            if      (dec_picture->ref_idx[LIST_1][j4][i4]==-1) 
+            if      (dec_picture->motion.ref_idx[LIST_1][j4][i4]==-1) 
             {
               direct_pdir = 0;
-              ref_idx  = (dec_picture->ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->ref_idx[LIST_0][j4][i4] : 0;
+              ref_idx  = (dec_picture->motion.ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_0][j4][i4] : 0;
             }
-            else if (dec_picture->ref_idx[LIST_0][j4][i4]==-1) 
+            else if (dec_picture->motion.ref_idx[LIST_0][j4][i4]==-1) 
             {
               direct_pdir = 1;
-              ref_idx  = (dec_picture->ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->ref_idx[LIST_1][j4][i4] : 0;
+              ref_idx  = (dec_picture->motion.ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_1][j4][i4] : 0;
             }
             else                                               
               direct_pdir = 2;
 
             pred_dir = direct_pdir;
 
-            dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]];
-            dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]];
+            dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
+            dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
           }
         }
         else
@@ -4586,16 +4722,16 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
 
             j6   = img->block_y_aff + j;
 
-            refList = (co_located_ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
-            ref_idx =  co_located_ref_idx[refList][j6][i4];
+            refList = (colocated->ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
+            ref_idx =  colocated->ref_idx[refList][j6][i4];
 
             if(ref_idx==-1) // co-located is intra mode
             {
-              memset( &dec_picture->mv  [LIST_0][j4][i4][0], 0, 2* sizeof(short));
-              memset( &dec_picture->mv  [LIST_1][j4][i4][0], 0, 2* sizeof(short));
+              memset( &dec_picture->motion.mv  [LIST_0][j4][i4][0], 0, 2* sizeof(short));
+              memset( &dec_picture->motion.mv  [LIST_1][j4][i4][0], 0, 2* sizeof(short));
 
-              dec_picture->ref_idx[LIST_0][j4][i4] = 0;
-              dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+              dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+              dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
             }
             else // co-located skip or inter mode
             {
@@ -4607,9 +4743,9 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
                 if(img->structure==0 && curr_mb_field==0)
                 {
                   // If the current MB is a frame MB and the colocated is from a field picture,
-                  // then the co_located_ref_id may have been generated from the wrong value of
+                  // then the colocated->ref_pic_id may have been generated from the wrong value of
                   // frame_poc if it references it's complementary field, so test both POC values
-                  if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][j6][i4])
+                  if(listX[0][iref]->top_poc*2 == colocated->ref_pic_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == colocated->ref_pic_id[refList][j6][i4])
                   {
                     mapped_idx=iref;
                     break;
@@ -4619,7 +4755,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
                   continue;
                 }
 
-                if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][j6][i4])
+                if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==colocated->ref_pic_id[refList][j6][i4])
                 {
                   mapped_idx=iref;
                   break;
@@ -4639,24 +4775,24 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
               //! In such case, an array is needed for each different reference.
               if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
               {
-                memcpy(&dec_picture->mv  [LIST_0][j4][i4][0], &co_located_mv[refList][j6][i4][0], 2 * sizeof(short));
-                memset(&dec_picture->mv  [LIST_1][j4][i4][0], 0, 2 * sizeof(short));
+                memcpy(&dec_picture->motion.mv  [LIST_0][j4][i4][0], &colocated->mv[refList][j6][i4][0], 2 * sizeof(short));
+                memset(&dec_picture->motion.mv  [LIST_1][j4][i4][0], 0, 2 * sizeof(short));
               }
               else
               {
-                dec_picture->mv  [LIST_0][j4][i4][0]=(mv_scale * co_located_mv[refList][j6][i4][0] + 128 ) >> 8;
-                dec_picture->mv  [LIST_0][j4][i4][1]=(mv_scale * co_located_mv[refList][j6][i4][1] + 128 ) >> 8;
+                dec_picture->motion.mv  [LIST_0][j4][i4][0]=(mv_scale * colocated->mv[refList][j6][i4][0] + 128 ) >> 8;
+                dec_picture->motion.mv  [LIST_0][j4][i4][1]=(mv_scale * colocated->mv[refList][j6][i4][1] + 128 ) >> 8;
 
-                dec_picture->mv  [LIST_1][j4][i4][0]=dec_picture->mv[LIST_0][j4][i4][0] - co_located_mv[refList][j6][i4][0] ;
-                dec_picture->mv  [LIST_1][j4][i4][1]=dec_picture->mv[LIST_0][j4][i4][1] - co_located_mv[refList][j6][i4][1] ;
+                dec_picture->motion.mv  [LIST_1][j4][i4][0]=dec_picture->motion.mv[LIST_0][j4][i4][0] - colocated->mv[refList][j6][i4][0] ;
+                dec_picture->motion.mv  [LIST_1][j4][i4][1]=dec_picture->motion.mv[LIST_0][j4][i4][1] - colocated->mv[refList][j6][i4][1] ;
               }
 
-              dec_picture->ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
-              dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+              dec_picture->motion.ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
+              dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
             }
             // store reference picture ID determined by direct mode
-            dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]];
-            dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]];
+            dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
+            dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
           }
         }
 
@@ -4668,15 +4804,15 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
         }
       }
     }
-    
-    iTransform(currMB, PLANE_Y, img, need_4x4_transform, smb); 
+
+    iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb); 
   }
-  
+
   if ((active_sps->chroma_format_idc==YUV444)&&(!IS_INDEPENDENT(img)))  
   {
     for (uv = 0; uv < 2; uv++ )
     {
-    
+
       if (IS_NEWINTRA (currMB))
       {
 
@@ -4684,13 +4820,13 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
         // -------------------------------------------
         if (uv==0) 
         {
-          intrapred_luma_16x16(currMB, PLANE_U, img, currMB->i16mode);
+          intrapred_luma_16x16(img, currMB, PLANE_U, currMB->i16mode);
           iMBtrans4x4(PLANE_U, img, smb); 
         }
         else
-        
+
         {
-          intrapred_luma_16x16(currMB, PLANE_V, img, currMB->i16mode);
+          intrapred_luma_16x16(img, currMB, PLANE_V, currMB->i16mode);
           iMBtrans4x4(PLANE_V, img, smb); 
         }
       }      
@@ -4710,22 +4846,22 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
             j4   = img->block_y + j;
             j_pos = j4 * BLOCK_SIZE;
             i_pos = i4 * BLOCK_SIZE;
-            
+
             // PREDICTION
             //===== INTRA PREDICTION =====
 
-            if (intrapred(currMB, (ColorPlane) (uv + 1), img, ioff, joff, i4,j4)==SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */
+            if (intrapred(img, currMB, (ColorPlane) (uv + 1), ioff, joff, i4,j4)==SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */
               return SEARCH_SYNC;                   /* bit error */
 
             // =============== 4x4 itrans ================
             // -------------------------------------------
-            itrans_4x4 ((ColorPlane) (uv + 1), img, ioff, joff);
-            
+            itrans_4x4 (img, (ColorPlane) (uv + 1), ioff, joff);
+
             for(jj=0;jj<BLOCK_SIZE;jj++)
             {
               for(ii=0;ii<BLOCK_SIZE;ii++)
               { 
-                dec_picture->imgUV[uv][j_pos + jj][i_pos + ii] = (imgpel) img->m7[uv+1][jj + joff][ii + ioff]; // construct picture from 4x4 blocks
+                dec_picture->imgUV[uv][j_pos + jj][i_pos + ii] = (imgpel) img->mb_rres[uv+1][jj + joff][ii + ioff]; // construct picture from 4x4 blocks
               }
             }
           }
@@ -4740,40 +4876,40 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
           //=========== 8x8 BLOCK TYPE ============
           ioff = 8 * (block8x8 & 0x01);
           joff = 8 * (block8x8 >> 1);
-          
+
           //PREDICTION
-          intrapred8x8((ColorPlane) (uv + 1), img, currMB, block8x8); 
+          intrapred8x8(img, currMB, (ColorPlane) (uv + 1), block8x8); 
           //For residual DPCM
-          itrans_8x8((ColorPlane) (uv + 1), img,ioff,joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
+          itrans_8x8(img, currMB, (ColorPlane) (uv + 1), ioff, joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
 
           for(jj = joff; jj < joff + 8;jj++)
           {
             for(ii = ioff; ii < ioff + 8;ii++)
             { 
-              dec_picture->imgUV[uv][img->pix_y + jj][img->pix_x + ii] = (imgpel) img->m7[uv+1][jj][ii]; // construct picture from 4x4 blocks
+              dec_picture->imgUV[uv][img->pix_y + jj][img->pix_x + ii] = (imgpel) img->mb_rres[uv+1][jj][ii]; // construct picture from 4x4 blocks
             }
           }
         }
       } //I8MB
-      
+
       else if ((img->type == P_SLICE) && (currMB->mb_type == PSKIP))
       {   
         block_size_x = MB_BLOCK_SIZE;
         block_size_y = MB_BLOCK_SIZE;
         i = 0;
         j = 0;
-        
+
         pred_dir = LIST_0;
         perform_mc((ColorPlane) (uv + 1), dec_picture, img,  pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
-        mpr = img->mpr[uv+1];
+        mpr = img->mb_pred[uv+1];
         curComp = dec_picture->imgUV[uv];
-        
+
         for(j = 0; j < img->mb_size[0][1]; j++)
         {                
           memcpy(&(curComp[img->pix_y + j][img->pix_x]), &(mpr[j][0]), img->mb_size[0][0] * sizeof(imgpel));
         }
       } //PSKIP
-      
+
       else if (currMB->mb_type == P16x16)
       {
         block_size_x = MB_BLOCK_SIZE;
@@ -4783,32 +4919,32 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
 
         pred_dir = currMB->b8pdir[0];  
         perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
-        iTransform(currMB, (ColorPlane) (uv + 1), img, need_4x4_transform, smb);   
+        iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);   
       } //P16x16
-      
+
       else if (currMB->mb_type == P16x8)
       {   
         block_size_x = MB_BLOCK_SIZE;
         block_size_y = 8;
-        
+
         for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
         {
           i = 0;
           j = block8x8;      
-          
+
           pred_dir = currMB->b8pdir[block8x8];
 
           perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);          
         }
-        iTransform(currMB, (ColorPlane) (uv + 1), img, need_4x4_transform, smb);
+        iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
 
       } //P16x8      
       else if (currMB->mb_type == P8x16)
       {   
-        
+
         block_size_x = 8;
         block_size_y = 16;
-        
+
         for (block8x8 = 0; block8x8 < 2; block8x8 ++)
         {
           i = block8x8<<1;
@@ -4818,7 +4954,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
           perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
         }
 
-        iTransform(currMB, (ColorPlane) (uv + 1), img, need_4x4_transform, smb);
+        iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
       } //P8x16
       else
       {
@@ -4826,22 +4962,22 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
         if (img->type==B_SLICE && img->direct_spatial_mv_pred_flag && (IS_DIRECT (currMB) ||
           (IS_P8x8(currMB) && !(currMB->b8mode[0] && currMB->b8mode[1] && currMB->b8mode[2] && currMB->b8mode[3]))))
           prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
-        
+
         for (block8x8=0; block8x8<4; block8x8++)
         {
           mv_mode  = currMB->b8mode[block8x8];
           pred_dir = currMB->b8pdir[block8x8];
-          
+
           //if ( mv_mode == SMB8x8 || mv_mode == SMB8x4 || mv_mode == SMB4x8 || mv_mode == SMB4x4 )
           if ( mv_mode != 0 )
           {
             int k_start = (block8x8 << 2);
             int k_inc = (mv_mode == SMB8x4) ? 2 : 1;
             int k_end = (mv_mode == SMB8x8) ? k_start + 1 : ((mv_mode == SMB4x4) ? k_start + 4 : k_start + k_inc + 1);
-            
+
             block_size_x = ( mv_mode == SMB8x4 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
             block_size_y = ( mv_mode == SMB4x8 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
-            
+
             for (k = k_start; k < k_end; k += k_inc)
             {
               i =  (decode_block_scan[k] & 3);
@@ -4854,7 +4990,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
           {
             int k_start = (block8x8 << 2);
             int k_end = k_start;
-            
+
             if (active_sps->direct_8x8_inference_flag)
             {
               block_size_x = SMB_BLOCK_SIZE;
@@ -4867,127 +5003,127 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
               block_size_y = BLOCK_SIZE;
               k_end += BLOCK_MULTIPLE;
             }
-            
+
             // Prepare mvs (needed for deblocking and mv prediction
             for (k = k_start; k < k_start + BLOCK_MULTIPLE; k ++)
             {
-              
+
               i =  (decode_block_scan[k] & 3);
               j = ((decode_block_scan[k] >> 2) & 3);
-              
+
               ioff = (i << 2);
               i4   = img->block_x + i;
-              
+
               joff = (j << 2);
               j4   = img->block_y + j;
-              
+
               assert (pred_dir<=2);
-              
+
               if (img->direct_spatial_mv_pred_flag)
               {
                 j6 = img->block_y_aff + j;
-                
+
                 //===== DIRECT PREDICTION =====              
                 if (l0_rFrame >=0)
                 {
-                  if (!l0_rFrame  && ((!moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                  if (!l0_rFrame  && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
                   {
-                    dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-                    dec_picture->mv  [LIST_0][j4][i4][1] = 0;
-                    dec_picture->ref_idx[LIST_0][j4][i4] = 0;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
+                    dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
                   }
                   else
                   {
-                    dec_picture->mv  [LIST_0][j4][i4][0] = pmvl0[0];
-                    dec_picture->mv  [LIST_0][j4][i4][1] = pmvl0[1];
-                    dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0] = pmvl0[0];
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1] = pmvl0[1];
+                    dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
                   }
                 }
                 else
                 {
-                  dec_picture->ref_idx[LIST_0][j4][i4] = -1;
-                  dec_picture->mv  [LIST_0][j4][i4][0] = 0;
-                  dec_picture->mv  [LIST_0][j4][i4][1] = 0;
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
+                  dec_picture->motion.mv  [LIST_0][j4][i4][0] = 0;
+                  dec_picture->motion.mv  [LIST_0][j4][i4][1] = 0;
                 }
-                
+
                 if (l1_rFrame >=0)
                 {
-                  if  (l1_rFrame==0 && ((!moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
+                  if  (l1_rFrame==0 && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
                   {
-                    
-                    dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-                    dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-                    dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
-                    
+
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+                    dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
+
                   }
                   else
                   {
-                    dec_picture->mv  [LIST_1][j4][i4][0] = pmvl1[0];
-                    dec_picture->mv  [LIST_1][j4][i4][1] = pmvl1[1];
-                    dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0] = pmvl1[0];
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1] = pmvl1[1];
+                    dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
                   }
                 }
                 else
                 {
-                  dec_picture->mv  [LIST_1][j4][i4][0] = 0;
-                  dec_picture->mv  [LIST_1][j4][i4][1] = 0;
-                  dec_picture->ref_idx[LIST_1][j4][i4] = -1;
+                  dec_picture->motion.mv  [LIST_1][j4][i4][0] = 0;
+                  dec_picture->motion.mv  [LIST_1][j4][i4][1] = 0;
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
                 }
-                
+
                 if (l0_rFrame < 0 && l1_rFrame < 0)
                 {
-                  dec_picture->ref_idx[LIST_0][j4][i4] = 0;
-                  dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
                 }
-                                               
-                if      (dec_picture->ref_idx[LIST_1][j4][i4]==-1) 
+
+                if      (dec_picture->motion.ref_idx[LIST_1][j4][i4]==-1) 
                 {
                   direct_pdir = 0;
-                  ref_idx  = (dec_picture->ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->ref_idx[LIST_0][j4][i4] : 0;
+                  ref_idx  = (dec_picture->motion.ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_0][j4][i4] : 0;
                 }
-                else if (dec_picture->ref_idx[LIST_0][j4][i4]==-1) 
+                else if (dec_picture->motion.ref_idx[LIST_0][j4][i4]==-1) 
                 {
                   direct_pdir = 1;
-                  ref_idx  = (dec_picture->ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->ref_idx[LIST_1][j4][i4] : 0;
+                  ref_idx  = (dec_picture->motion.ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_1][j4][i4] : 0;
                 }
                 else                                               
                   direct_pdir = 2;
-                
+
                 pred_dir = direct_pdir;
-                
+
               }
               else
               {
                 j6= img->block_y_aff + j;
-                
-                refList = (co_located_ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
-                ref_idx =  co_located_ref_idx[refList][j6][i4];
-                
+
+                refList = (colocated->ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
+                ref_idx =  colocated->ref_idx[refList][j6][i4];
+
                 if(ref_idx==-1) // co-located is intra mode
                 {
                   for(hv=0; hv<2; hv++)
                   {
-                    dec_picture->mv  [LIST_0][j4][i4][hv]=0;
-                    dec_picture->mv  [LIST_1][j4][i4][hv]=0;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][hv]=0;
+                    dec_picture->motion.mv  [LIST_1][j4][i4][hv]=0;
                   }
-                  
-                  dec_picture->ref_idx[LIST_0][j4][i4] = 0;
-                  dec_picture->ref_idx[LIST_1][j4][i4] = 0;
+
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
                 }
                 else // co-located skip or inter mode
                 {
                   int mapped_idx=0;
                   int iref;
-                  
+
                   {
                     for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++)
                     {
                       if(img->structure==0 && curr_mb_field==0)
                       {
                         // If the current MB is a frame MB and the colocated is from a field picture,
-                        // then the co_located_ref_id may have been generated from the wrong value of
+                        // then the colocated->ref_pic_id may have been generated from the wrong value of
                         // frame_poc if it references it's complementary field, so test both POC values
-                        if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][j6][i4])
+                        if(listX[0][iref]->top_poc*2 == colocated->ref_pic_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == colocated->ref_pic_id[refList][j6][i4])
                         {
                           mapped_idx=iref;
                           break;
@@ -4996,8 +5132,8 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
                           mapped_idx=INVALIDINDEX;
                         continue;
                       }
-                      
-                      if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][j6][i4])
+
+                      if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==colocated->ref_pic_id[refList][j6][i4])
                       {
                         mapped_idx=iref;
                         break;
@@ -5012,39 +5148,39 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
                       error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
                     }
                   }
-                  
+
                   mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
-                  
+
                   //! In such case, an array is needed for each different reference.
                   if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
                   {
-                    dec_picture->mv  [LIST_0][j4][i4][0]=co_located_mv[refList][j6][i4][0];
-                    dec_picture->mv  [LIST_0][j4][i4][1]=co_located_mv[refList][j6][i4][1];
-                    
-                    dec_picture->mv  [LIST_1][j4][i4][0]=0;
-                    dec_picture->mv  [LIST_1][j4][i4][1]=0;
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0]=colocated->mv[refList][j6][i4][0];
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1]=colocated->mv[refList][j6][i4][1];
+
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0]=0;
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1]=0;
                   }
                   else
                   {
-                    dec_picture->mv  [LIST_0][j4][i4][0] = (short) ((mv_scale * co_located_mv[refList][j6][i4][0] + 128 ) >> 8);
-                    dec_picture->mv  [LIST_0][j4][i4][1] = (short) ((mv_scale * co_located_mv[refList][j6][i4][1] + 128 ) >> 8);
-                    
-                    dec_picture->mv  [LIST_1][j4][i4][0] = (short) (dec_picture->mv[LIST_0][j4][i4][0] - co_located_mv[refList][j6][i4][0]);
-                    dec_picture->mv  [LIST_1][j4][i4][1] = (short) (dec_picture->mv[LIST_0][j4][i4][1] - co_located_mv[refList][j6][i4][1]);
+                    dec_picture->motion.mv  [LIST_0][j4][i4][0] = (short) ((mv_scale * colocated->mv[refList][j6][i4][0] + 128 ) >> 8);
+                    dec_picture->motion.mv  [LIST_0][j4][i4][1] = (short) ((mv_scale * colocated->mv[refList][j6][i4][1] + 128 ) >> 8);
+
+                    dec_picture->motion.mv  [LIST_1][j4][i4][0] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][0] - colocated->mv[refList][j6][i4][0]);
+                    dec_picture->motion.mv  [LIST_1][j4][i4][1] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][1] - colocated->mv[refList][j6][i4][1]);
                   }
-                  
-                  dec_picture->ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
-                  dec_picture->ref_idx[LIST_1][j4][i4] = 0;                  
+
+                  dec_picture->motion.ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
+                  dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;                  
                 }
               }
               // store reference picture ID determined by direct mode
-              dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]];
-              dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]];
+              dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
+              dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
             }
-            
+
             for (k = k_start; k < k_end; k ++)
             {
-              
+
               i =  (decode_block_scan[k] & 3);
               j = ((decode_block_scan[k] >> 2) & 3);
 
@@ -5052,7 +5188,7 @@ int decode_one_macroblock(Macroblock *currMB, ImageParameters *img)
             }
           }
         }
-        iTransform(currMB, (ColorPlane) (uv + 1), img, need_4x4_transform, smb);
+        iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
       }
     } 
   }  
@@ -5092,10 +5228,12 @@ void make_frame_picture_JV()
   // Copy Storable Params
   for( nplane=0; nplane<MAX_PLANE; nplane++ )
   {
-    copy_storable_param_JV( nplane, dec_picture, dec_picture_JV[nplane] );
+    copy_storable_param_JV( &dec_picture->JVmotion[nplane], &dec_picture_JV[nplane]->motion );
   }
 
-  for( uv=0; uv<2; uv++ ){
+  // This could be done with pointers and seems not necessary
+  for( uv=0; uv<2; uv++ )
+  {
     for( line=0; line<img->height; line++ )
     {
       nsize = sizeof(imgpel) * img->width;
diff --git a/ldecod/src/mb_access.c b/ldecod/src/mb_access.c
index da1815d..eb9f4c4 100644
--- a/ldecod/src/mb_access.c
+++ b/ldecod/src/mb_access.c
@@ -133,8 +133,8 @@ void get_mb_pos (int mb_addr, int mb_size[2], int *x, int*y)
  *    input x position
  * \param yN
  *    input y position
- * \param is_chroma
- *    0 if luma coding, 1 for chroma
+ * \param mb_size
+ *    Macroblock size in pixel (according to luma or chroma MB access)
  * \param pix
  *    returns position informations
  ************************************************************************
@@ -206,8 +206,8 @@ void getNonAffNeighbour(Macroblock *currMb, int xN, int yN, int mb_size[2], Pixe
  *    input x position
  * \param yN
  *    input y position
- * \param is_chroma
- *    0 if luma coding, 1 for chroma
+ * \param mb_size
+ *    Macroblock size in pixel (according to luma or chroma MB access)
  * \param pix
  *    returns position informations
  ************************************************************************
diff --git a/ldecod/src/mbuffer.c b/ldecod/src/mbuffer.c
index 927a8ab..dcc9a8e 100644
--- a/ldecod/src/mbuffer.c
+++ b/ldecod/src/mbuffer.c
@@ -65,6 +65,7 @@ void dump_dpb(void)
 {
 #if DUMP_DPB
   unsigned i;
+
   for (i=0; i<dpb.used_size;i++)
   {
     printf("(");
@@ -121,10 +122,10 @@ int getDpbSize(void)
     size = 152064;
     break;
   case 11:
-    if (!IS_FREXT_PROFILE(active_sps->profile_idc)&&(active_sps->constrained_set3_flag == 0))
-      size = 345600;
-    else
+    if (!IS_FREXT_PROFILE(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1))
       size = 152064;
+    else
+      size = 345600;
     break;
   case 12:
     size = 912384;
@@ -156,12 +157,9 @@ int getDpbSize(void)
   case 41:
     size = 12582912;
     break;
- case 42:
-    if( IS_FREXT_PROFILE(active_sps->profile_idc) )
-     size = 13369344;
-   else
-     size = 12582912;
-   break;
+  case 42:
+    size = 13369344;
+    break;
   case 50:
     size = 42393600;
     break;
@@ -364,6 +362,20 @@ FrameStore* alloc_frame_store(void)
   return f;
 }
 
+void alloc_pic_motion(PicMotionParams *motion, int size_y, int size_x)
+{
+  get_mem3Dint64 (&(motion->ref_pic_id), 6, size_y, size_x);
+  get_mem3Dint64 (&(motion->ref_id),     6, size_y, size_x);
+  get_mem4Dshort (&(motion->mv),         2, size_y, size_x, 2);
+  get_mem3D      ((byte****)(&(motion->ref_idx)),    2, size_y , size_x);
+
+  motion->mb_field = calloc (size_y * size_x, sizeof(int));
+  if (motion->mb_field == NULL)
+    no_mem_exit("alloc_storable_picture: motion->mb_field");
+
+  get_mem2D (&(motion->field_frame), size_y, size_x);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -408,32 +420,18 @@ StorablePicture* alloc_storable_picture(PictureStructure structure, int size_x,
   if (active_sps->chroma_format_idc != YUV400)
     get_mem3Dpel (&(s->imgUV), 2, size_y_cr, size_x_cr);
   
-
-  s->mb_field = calloc (s->PicSizeInMbs, sizeof(int));
-  if (NULL==s->mb_field)
-    no_mem_exit("alloc_storable_picture: s->mb_field");
-
   get_mem2Dshort (&(s->slice_id), size_y / MB_BLOCK_SIZE, size_x / MB_BLOCK_SIZE);
 
-  get_mem3D      ((byte****)(&(s->ref_idx))   , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_pic_id), 6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_id)    , 6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem4Dshort (&(s->mv)        , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
+  alloc_pic_motion(&s->motion, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
 
   if( IS_INDEPENDENT(img) )
   {
     for( nplane=0; nplane<MAX_PLANE; nplane++ )
     {
-      get_mem3D      ((byte****)(&(s->ref_idx_JV[nplane])),    2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem3Dint64 (&(s->ref_pic_id_JV[nplane]), 6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem3Dint64 (&(s->ref_id_JV[nplane]),     6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem4Dshort (&(s->mv_JV[nplane]),         2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
+      alloc_pic_motion(&s->JVmotion[nplane], size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
     }
   }
 
-  get_mem2D      (&(s->moving_block), size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem2D      (&(s->field_frame) , size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-
   s->pic_num=0;
   s->frame_num=0;
   s->long_term_frame_idx=0;
@@ -503,6 +501,45 @@ void free_frame_store(FrameStore* f)
   }
 }
 
+void free_pic_motion(PicMotionParams *motion)
+{
+  if (motion->ref_pic_id)
+  {
+    free_mem3Dint64 (motion->ref_pic_id);
+    motion->ref_pic_id = NULL;
+  }
+  if (motion->ref_id)
+  {
+    free_mem3Dint64 (motion->ref_id);
+    motion->ref_id = NULL;
+  }
+
+  if (motion->mv)
+  {
+    free_mem4Dshort (motion->mv);
+    motion->mv = NULL;
+  }
+
+  if (motion->ref_idx)
+  {
+    free_mem3D ((byte***)motion->ref_idx);
+    motion->ref_idx = NULL;
+  }
+
+  if (motion->mb_field)
+  {
+    free(motion->mb_field);
+    motion->mb_field = NULL;
+  }
+
+  if (motion->field_frame)
+  {
+    free_mem2D (motion->field_frame);
+    motion->field_frame=NULL;
+  }
+}
+
+
 /*!
  ************************************************************************
  * \brief
@@ -518,69 +555,16 @@ void free_storable_picture(StorablePicture* p)
   int nplane;
   if (p)
   {
-    if (p->ref_idx)
-    {
-      free_mem3D ((byte***)p->ref_idx);
-      p->ref_idx = NULL;
-    }
-
-    if (p->ref_pic_id)
-    {
-      free_mem3Dint64 (p->ref_pic_id);
-      p->ref_pic_id = NULL;
-    }
-
-    if (p->ref_id)
-    {
-      free_mem3Dint64 (p->ref_id);
-      p->ref_id = NULL;
-    }
-
-    if (p->mv)
-    {
-      free_mem4Dshort (p->mv);
-      p->mv = NULL;
-    }
+    free_pic_motion(&p->motion);
 
     if( IS_INDEPENDENT(img) )
     {
       for( nplane=0; nplane<MAX_PLANE; nplane++ )
       {
-        if (p->ref_idx_JV[nplane])
-        {
-          free_mem3D ((byte***)p->ref_idx_JV[nplane]);
-          p->ref_idx_JV[nplane] = NULL;
-        }    
-        if (p->ref_pic_id_JV[nplane])
-        {
-          free_mem3Dint64 (p->ref_pic_id_JV[nplane]);
-          p->ref_pic_id_JV[nplane] = NULL;
-        }
-        if (p->ref_id_JV[nplane])
-        {
-          free_mem3Dint64 (p->ref_id_JV[nplane]);
-          p->ref_id_JV[nplane] = NULL;
-        }
-        if (p->mv_JV[nplane])
-        {
-          free_mem4Dshort (p->mv_JV[nplane]);
-          p->mv_JV[nplane] = NULL;
-        }
+        free_pic_motion(&p->JVmotion[nplane]);
       }
     }
 
-    if (p->moving_block)
-    {
-      free_mem2D (p->moving_block);
-      p->moving_block=NULL;
-    }
-
-    if (p->field_frame)
-    {
-      free_mem2D (p->field_frame);
-      p->field_frame=NULL;
-    }
-
     if (p->imgY)
     {
       free_mem2Dpel (p->imgY);
@@ -593,12 +577,6 @@ void free_storable_picture(StorablePicture* p)
       p->imgUV=NULL;
     }
 
-    if (p->mb_field)
-    {
-      free(p->mb_field);
-      p->mb_field=NULL;
-    }
-
     if (p->slice_id)
     {
       free_mem2Dshort(p->slice_id);
@@ -651,46 +629,18 @@ static void unmark_for_reference(FrameStore* fs)
 
   if(fs->frame)
   {
-    if (fs->frame->ref_pic_id)
-    {
-      free_mem3Dint64 (fs->frame->ref_pic_id);
-      fs->frame->ref_pic_id = NULL;
-    }
-    if (fs->frame->ref_id)
-    {
-      free_mem3Dint64 (fs->frame->ref_id);
-      fs->frame->ref_id = NULL;
-    }
+    free_pic_motion(&fs->frame->motion);
   }
 
   if (fs->top_field)
   {
-    if (fs->top_field->ref_pic_id)
-    {
-      free_mem3Dint64 (fs->top_field->ref_pic_id);
-      fs->top_field->ref_pic_id = NULL;
-    }
-    if (fs->top_field->ref_id)
-    {
-      free_mem3Dint64 (fs->top_field->ref_id);
-      fs->top_field->ref_id = NULL;
-    }
-
+    free_pic_motion(&fs->top_field->motion);
   }
+
   if (fs->bottom_field)
   {
-    if (fs->bottom_field->ref_pic_id)
-    {
-      free_mem3Dint64 (fs->bottom_field->ref_pic_id);
-      fs->bottom_field->ref_pic_id = NULL;
-    }
-    if (fs->bottom_field->ref_id)
-    {
-      free_mem3Dint64 (fs->bottom_field->ref_id);
-      fs->bottom_field->ref_id = NULL;
-    }
+    free_pic_motion(&fs->bottom_field->motion);
   }
-
 }
 
 
@@ -1044,7 +994,7 @@ void init_lists(int currSliceType, PictureStructure currPicStructure)
       }
     }
     // update long_term_pic_num
-    for (i=0; i<dpb.ltref_frames_in_buffer; i++)
+    for (i = 0; i < dpb.ltref_frames_in_buffer; i++)
     {
       if (dpb.fs_ltref[i]->is_used==3)
       {
@@ -1435,7 +1385,7 @@ static StorablePicture*  get_short_term_pic(int picNum)
           return dpb.fs_ref[i]->bottom_field;
     }
   }
-//  return NULL;
+
   return no_reference_picture;
 }
 
@@ -2892,12 +2842,12 @@ void gen_field_ref_ids(StorablePicture *p)
   {
     for (j=0 ; j<p->size_y/4 ; j++)
     {
-        dummylist0= p->ref_idx[LIST_0][j][i];
-        dummylist1= p->ref_idx[LIST_1][j][i];
+        dummylist0= p->motion.ref_idx[LIST_0][j][i];
+        dummylist1= p->motion.ref_idx[LIST_1][j][i];
         //! association with id already known for fields.
-        p->ref_id[LIST_0][j][i] = (dummylist0>=0)? p->ref_pic_num[p->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
-        p->ref_id[LIST_1][j][i] = (dummylist1>=0)? p->ref_pic_num[p->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
-        p->field_frame[j][i]=1;
+        p->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? p->ref_pic_num[p->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
+        p->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? p->ref_pic_num[p->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
+        p->motion.field_frame[j][i]=1;
     }
   }
 }
@@ -3001,25 +2951,25 @@ void dpb_split_field(FrameStore *fs)
       idiv = (i >> 2);
       currentmb = twosz16*(jdiv >> 1)+ (idiv)*2 + (jdiv & 0x01);
 
-      if (fs->frame->MbaffFrameFlag && fs->frame->mb_field[currentmb])
+      if (fs->frame->MbaffFrameFlag && fs->frame->motion.mb_field[currentmb])
       {
         int list_offset = currentmb%2? 4: 2;
-        dummylist0 = fs->frame->ref_idx[LIST_0][j][i];
-        dummylist1 = fs->frame->ref_idx[LIST_1][j][i];
+        dummylist0 = fs->frame->motion.ref_idx[LIST_0][j][i];
+        dummylist1 = fs->frame->motion.ref_idx[LIST_1][j][i];
         //! association with id already known for fields.
-        fs->frame->ref_id[LIST_0 + list_offset][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0 + list_offset][dummylist0] : 0;
-        fs->frame->ref_id[LIST_1 + list_offset][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1 + list_offset][dummylist1] : 0;
+        fs->frame->motion.ref_id[LIST_0 + list_offset][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0 + list_offset][dummylist0] : 0;
+        fs->frame->motion.ref_id[LIST_1 + list_offset][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1 + list_offset][dummylist1] : 0;
         //! need to make association with frames
-        fs->frame->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->frm_ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0 + list_offset][dummylist0] : 0;
-        fs->frame->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->frm_ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1 + list_offset][dummylist1] : 0;
+        fs->frame->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->frm_ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0 + list_offset][dummylist0] : 0;
+        fs->frame->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->frm_ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1 + list_offset][dummylist1] : 0;
 
       }
       else
       {
-        dummylist0 = fs->frame->ref_idx[LIST_0][j][i];
-        dummylist1 = fs->frame->ref_idx[LIST_1][j][i];
-        fs->frame->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0][dummylist0] : -1;
-        fs->frame->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1][dummylist1] : -1;
+        dummylist0 = fs->frame->motion.ref_idx[LIST_0][j][i];
+        dummylist1 = fs->frame->motion.ref_idx[LIST_1][j][i];
+        fs->frame->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_0][dummylist0] : -1;
+        fs->frame->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[fs->frame->slice_id[jdiv][idiv]][LIST_1][dummylist1] : -1;
       }
     }
   }
@@ -3037,29 +2987,29 @@ void dpb_split_field(FrameStore *fs)
 
         currentmb = twosz16*(jdiv >> 1)+ (idiv)*2 + (jdiv & 0x01);
         // Assign field mvs attached to MB-Frame buffer to the proper buffer
-        if (fs->frame->mb_field[currentmb])
+        if (fs->frame->motion.mb_field[currentmb])
         {
-          fs->bottom_field->field_frame[j][i] = fs->top_field->field_frame[j][i]=1;
-          fs->frame->field_frame[2*j][i] = fs->frame->field_frame[2*j+1][i]=1;
-
-          fs->bottom_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj4][i][0];
-          fs->bottom_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj4][i][1];
-          fs->bottom_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj4][i][0];
-          fs->bottom_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj4][i][1];
-          fs->bottom_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj4][i];
-          fs->bottom_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj4][i];
-          fs->bottom_field->ref_id[LIST_0][j][i] = fs->frame->ref_id[LIST_0+4][jj4][i];
-          fs->bottom_field->ref_id[LIST_1][j][i] = fs->frame->ref_id[LIST_1+4][jj4][i];
-
-
-          fs->top_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj][i][0];
-          fs->top_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj][i][1];
-          fs->top_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj][i][0];
-          fs->top_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj][i][1];
-          fs->top_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj][i];
-          fs->top_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj][i];
-          fs->top_field->ref_id[LIST_0][j][i] = fs->frame->ref_id[LIST_0+2][jj][i];
-          fs->top_field->ref_id[LIST_1][j][i] = fs->frame->ref_id[LIST_1+2][jj][i];
+          fs->bottom_field->motion.field_frame[j][i] = fs->top_field->motion.field_frame[j][i]=1;
+          fs->frame->motion.field_frame[2*j][i] = fs->frame->motion.field_frame[2*j+1][i]=1;
+
+          fs->bottom_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj4][i][0];
+          fs->bottom_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj4][i][1];
+          fs->bottom_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj4][i][0];
+          fs->bottom_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj4][i][1];
+          fs->bottom_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj4][i];
+          fs->bottom_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj4][i];
+          fs->bottom_field->motion.ref_id[LIST_0][j][i] = fs->frame->motion.ref_id[LIST_0+4][jj4][i];
+          fs->bottom_field->motion.ref_id[LIST_1][j][i] = fs->frame->motion.ref_id[LIST_1+4][jj4][i];
+
+
+          fs->top_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj][i][0];
+          fs->top_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj][i][1];
+          fs->top_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj][i][0];
+          fs->top_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj][i][1];
+          fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj][i];
+          fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj][i];
+          fs->top_field->motion.ref_id[LIST_0][j][i] = fs->frame->motion.ref_id[LIST_0+2][jj][i];
+          fs->top_field->motion.ref_id[LIST_1][j][i] = fs->frame->motion.ref_id[LIST_1+2][jj][i];
         }
       }
     }
@@ -3079,47 +3029,47 @@ void dpb_split_field(FrameStore *fs)
 
         currentmb = twosz16 * (jdiv >> 1)+ (idiv)*2 + (jdiv & 0x01);
 
-        if (!fs->frame->MbaffFrameFlag  || !fs->frame->mb_field[currentmb])
+        if (!fs->frame->MbaffFrameFlag  || !fs->frame->motion.mb_field[currentmb])
         {
-          fs->frame->field_frame[2*j+1][i] = fs->frame->field_frame[2*j][i]=0;
+          fs->frame->motion.field_frame[2*j+1][i] = fs->frame->motion.field_frame[2*j][i]=0;
 
-          fs->top_field->field_frame[j][i] = fs->bottom_field->field_frame[j][i] = 0;
+          fs->top_field->motion.field_frame[j][i] = fs->bottom_field->motion.field_frame[j][i] = 0;
 
-          fs->top_field->mv[LIST_0][j][i][0] = fs->bottom_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj][ii][0];
-          fs->top_field->mv[LIST_0][j][i][1] = fs->bottom_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj][ii][1];
-          fs->top_field->mv[LIST_1][j][i][0] = fs->bottom_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj][ii][0];
-          fs->top_field->mv[LIST_1][j][i][1] = fs->bottom_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj][ii][1];
+          fs->top_field->motion.mv[LIST_0][j][i][0] = fs->bottom_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj][ii][0];
+          fs->top_field->motion.mv[LIST_0][j][i][1] = fs->bottom_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj][ii][1];
+          fs->top_field->motion.mv[LIST_1][j][i][0] = fs->bottom_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj][ii][0];
+          fs->top_field->motion.mv[LIST_1][j][i][1] = fs->bottom_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
-          if (fs->frame->ref_idx[LIST_0][jj][ii] == -1)
-            fs->top_field->ref_idx[LIST_0][j][i] = fs->bottom_field->ref_idx[LIST_0][j][i] = - 1;
+          if (fs->frame->motion.ref_idx[LIST_0][jj][ii] == -1)
+            fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->bottom_field->motion.ref_idx[LIST_0][j][i] = - 1;
           else
           {
-            dummylist0=fs->top_field->ref_idx[LIST_0][j][i] = fs->bottom_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj][ii] ;
-            fs->top_field   ->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->top_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_0][dummylist0] : 0;
-            fs->bottom_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->bottom_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_0][dummylist0] : 0;
+            dummylist0=fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->bottom_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj][ii] ;
+            fs->top_field   ->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->top_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_0][dummylist0] : 0;
+            fs->bottom_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->bottom_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_0][dummylist0] : 0;
           }
 
-          if (fs->frame->ref_idx[LIST_1][jj][ii] == -1)
-            fs->top_field->ref_idx[LIST_1][j][i] = fs->bottom_field->ref_idx[LIST_1][j][i] = - 1;
+          if (fs->frame->motion.ref_idx[LIST_1][jj][ii] == -1)
+            fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->bottom_field->motion.ref_idx[LIST_1][j][i] = - 1;
           else
           {
-            dummylist1=fs->top_field->ref_idx[LIST_1][j][i] = fs->bottom_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj][ii];
+            dummylist1=fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->bottom_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj][ii];
 
-            fs->top_field   ->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->top_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_1][dummylist1] : 0;
-            fs->bottom_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->bottom_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_1][dummylist1] : 0;
+            fs->top_field   ->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->top_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_1][dummylist1] : 0;
+            fs->bottom_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->bottom_ref_pic_num[fs->frame->slice_id[jj>>2][ii>>2]][LIST_1][dummylist1] : 0;
           }
         }
         else
         {
-          fs->frame->field_frame[2*j+1][i] = fs->frame->field_frame[2*j][i]= fs->frame->mb_field[currentmb];
+          fs->frame->motion.field_frame[2*j+1][i] = fs->frame->motion.field_frame[2*j][i]= fs->frame->motion.mb_field[currentmb];
         }
       }
     }
   }
   else
   {
-    memset( &(fs->frame->field_frame[0][0]), 0, (fs->frame->size_y * fs->frame->size_x >> 4) * sizeof(byte));
+    memset( &(fs->frame->motion.field_frame[0][0]), 0, (fs->frame->size_y * fs->frame->size_x >> 4) * sizeof(byte));
   }
 }
 
@@ -3220,41 +3170,41 @@ void dpb_combine_field(FrameStore *fs)
     jj4 = jj + 4;
     for (i=0 ; i< (fs->top_field->size_x >> 2) ; i++)
     {
-      fs->frame->field_frame[jj][i]= fs->frame->field_frame[jj4][i]=1;
+      fs->frame->motion.field_frame[jj][i]= fs->frame->motion.field_frame[jj4][i]=1;
 
-      fs->frame->mv[LIST_0][jj][i][0] = fs->top_field->mv[LIST_0][j][i][0];
-      fs->frame->mv[LIST_0][jj][i][1] = fs->top_field->mv[LIST_0][j][i][1];
-      fs->frame->mv[LIST_1][jj][i][0] = fs->top_field->mv[LIST_1][j][i][0];
-      fs->frame->mv[LIST_1][jj][i][1] = fs->top_field->mv[LIST_1][j][i][1];
+      fs->frame->motion.mv[LIST_0][jj][i][0] = fs->top_field->motion.mv[LIST_0][j][i][0];
+      fs->frame->motion.mv[LIST_0][jj][i][1] = fs->top_field->motion.mv[LIST_0][j][i][1];
+      fs->frame->motion.mv[LIST_1][jj][i][0] = fs->top_field->motion.mv[LIST_1][j][i][0];
+      fs->frame->motion.mv[LIST_1][jj][i][1] = fs->top_field->motion.mv[LIST_1][j][i][1];
 
-      dummylist0=fs->frame->ref_idx[LIST_0][jj][i]  = fs->top_field->ref_idx[LIST_0][j][i];
-      dummylist1=fs->frame->ref_idx[LIST_1][jj][i]  = fs->top_field->ref_idx[LIST_1][j][i];
+      dummylist0=fs->frame->motion.ref_idx[LIST_0][jj][i]  = fs->top_field->motion.ref_idx[LIST_0][j][i];
+      dummylist1=fs->frame->motion.ref_idx[LIST_1][jj][i]  = fs->top_field->motion.ref_idx[LIST_1][j][i];
 
       //! association with id already known for fields.
-      fs->top_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->top_field->ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
-      fs->top_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->top_field->ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
+      fs->top_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->top_field->ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
+      fs->top_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->top_field->ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
 
       //! need to make association with frames
-      fs->frame->ref_id[LIST_0][jj][i] = (dummylist0>=0)? fs->top_field->frm_ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
-      fs->frame->ref_id[LIST_1][jj][i] = (dummylist1>=0)? fs->top_field->frm_ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
+      fs->frame->motion.ref_id[LIST_0][jj][i] = (dummylist0>=0)? fs->top_field->frm_ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
+      fs->frame->motion.ref_id[LIST_1][jj][i] = (dummylist1>=0)? fs->top_field->frm_ref_pic_num[fs->top_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
 
-      fs->frame->mv[LIST_0][jj4][i][0] = fs->bottom_field->mv[LIST_0][j][i][0];
-      fs->frame->mv[LIST_0][jj4][i][1] = fs->bottom_field->mv[LIST_0][j][i][1] ;
-      fs->frame->mv[LIST_1][jj4][i][0] = fs->bottom_field->mv[LIST_1][j][i][0];
-      fs->frame->mv[LIST_1][jj4][i][1] = fs->bottom_field->mv[LIST_1][j][i][1] ;
+      fs->frame->motion.mv[LIST_0][jj4][i][0] = fs->bottom_field->motion.mv[LIST_0][j][i][0];
+      fs->frame->motion.mv[LIST_0][jj4][i][1] = fs->bottom_field->motion.mv[LIST_0][j][i][1] ;
+      fs->frame->motion.mv[LIST_1][jj4][i][0] = fs->bottom_field->motion.mv[LIST_1][j][i][0];
+      fs->frame->motion.mv[LIST_1][jj4][i][1] = fs->bottom_field->motion.mv[LIST_1][j][i][1] ;
 
-      dummylist0=fs->frame->ref_idx[LIST_0][jj4][i]  = fs->bottom_field->ref_idx[LIST_0][j][i];
-      dummylist1=fs->frame->ref_idx[LIST_1][jj4][i]  = fs->bottom_field->ref_idx[LIST_1][j][i];
+      dummylist0=fs->frame->motion.ref_idx[LIST_0][jj4][i]  = fs->bottom_field->motion.ref_idx[LIST_0][j][i];
+      dummylist1=fs->frame->motion.ref_idx[LIST_1][jj4][i]  = fs->bottom_field->motion.ref_idx[LIST_1][j][i];
 
-      fs->bottom_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->bottom_field->ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
-      fs->bottom_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->bottom_field->ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
+      fs->bottom_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->bottom_field->ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : 0;
+      fs->bottom_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->bottom_field->ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : 0;
 
       //! need to make association with frames
-      fs->frame->ref_id[LIST_0][jj4][i] = (dummylist0>=0)? fs->bottom_field->frm_ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : -1;
-      fs->frame->ref_id[LIST_1][jj4][i] = (dummylist1>=0)? fs->bottom_field->frm_ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : -1;
+      fs->frame->motion.ref_id[LIST_0][jj4][i] = (dummylist0>=0)? fs->bottom_field->frm_ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_0][dummylist0] : -1;
+      fs->frame->motion.ref_id[LIST_1][jj4][i] = (dummylist1>=0)? fs->bottom_field->frm_ref_pic_num[fs->bottom_field->slice_id[j>>2][i>>2]][LIST_1][dummylist1] : -1;
 
-      fs->top_field->field_frame[j][i]=1;
-      fs->bottom_field->field_frame[j][i]=1;
+      fs->top_field->motion.field_frame[j][i]=1;
+      fs->bottom_field->motion.field_frame[j][i]=1;
     }
   }
 }
@@ -3392,6 +3342,21 @@ void fill_frame_num_gap(ImageParameters *img)
 
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate motion parameter memory for colocated structure
+ *
+ ************************************************************************
+ */
+void alloc_motion_params(MotionParams *ftype, int size_y, int size_x)
+{
+  get_mem3Dint64 (&(ftype->ref_pic_id), 2, size_y, size_x);
+  get_mem4Dshort (&(ftype->mv)        , 2, size_y, size_x, 2);
+  get_mem3D      ((byte****)(&(ftype->ref_idx)) , 2, size_y, size_x);
+  get_mem2D      (&(ftype->moving_block) , size_y, size_x);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -3419,25 +3384,12 @@ ColocatedParams* alloc_colocated(int size_x, int size_y, int mb_adaptive_frame_f
   s->size_x = size_x;
   s->size_y = size_y;
 
-
-  get_mem3D      ((byte****)(&(s->ref_idx))   , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_pic_id), 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem4Dshort (&(s->mv)        , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
-
-  get_mem2D      (&(s->moving_block), size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem2D      (&(s->field_frame) , size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
+  alloc_motion_params(&s->frame, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
 
   if (mb_adaptive_frame_field_flag)
   {
-    get_mem3D      ((byte****)(&(s->top_ref_idx))   , 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
-    get_mem3Dint64 (&(s->top_ref_pic_id), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
-    get_mem4Dshort (&(s->top_mv),         2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE, 2);
-    get_mem2D (&(s->top_moving_block),       size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
-
-    get_mem3D      ((byte****)(&(s->bottom_ref_idx)),    2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
-    get_mem3Dint64 (&(s->bottom_ref_pic_id), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
-    get_mem4Dshort (&(s->bottom_mv),         2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE, 2);
-    get_mem2D (&(s->bottom_moving_block),       size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
+    alloc_motion_params(&s->top   , size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
+    alloc_motion_params(&s->bottom, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
   }
 
   s->mb_adaptive_frame_field_flag  = mb_adaptive_frame_field_flag;
@@ -3459,43 +3411,38 @@ void free_colocated(ColocatedParams* p)
 {
   if (p)
   {
-    free_mem3D      ((byte***)p->ref_idx);
-    free_mem3Dint64 (p->ref_pic_id);
-    free_mem4Dshort (p->mv);
+    free_mem3D      ((byte***)p->frame.ref_idx);
+    free_mem3Dint64 (p->frame.ref_pic_id);
+    free_mem4Dshort (p->frame.mv);
 
-    if (p->moving_block)
-    {
-      free_mem2D (p->moving_block);
-      p->moving_block=NULL;
-    }
-    if (p->field_frame)
+    if (p->frame.moving_block)
     {
-      free_mem2D (p->field_frame);
-      p->field_frame=NULL;
+      free_mem2D (p->frame.moving_block);
+      p->frame.moving_block=NULL;
     }
 
     if (p->mb_adaptive_frame_field_flag)
     {
-      free_mem3D      ((byte***)p->top_ref_idx);
-      free_mem3Dint64 (p->top_ref_pic_id);
-      free_mem4Dshort (p->top_mv);
+      free_mem3D      ((byte***)p->top.ref_idx);
+      free_mem3Dint64 (p->top.ref_pic_id);
+      free_mem4Dshort (p->top.mv);
 
 
-      if (p->top_moving_block)
+      if (p->top.moving_block)
       {
-        free_mem2D (p->top_moving_block);
-        p->top_moving_block=NULL;
+        free_mem2D (p->top.moving_block);
+        p->top.moving_block=NULL;
       }
 
-      free_mem3D      ((byte***)p->bottom_ref_idx);
-      free_mem3Dint64 (p->bottom_ref_pic_id);
-      free_mem4Dshort (p->bottom_mv);
+      free_mem3D      ((byte***)p->bottom.ref_idx);
+      free_mem3Dint64 (p->bottom.ref_pic_id);
+      free_mem4Dshort (p->bottom.mv);
 
 
-      if (p->bottom_moving_block)
+      if (p->bottom.moving_block)
       {
-        free_mem2D (p->bottom_moving_block);
-        p->bottom_moving_block=NULL;
+        free_mem2D (p->bottom.moving_block);
+        p->bottom.moving_block=NULL;
       }
 
     }
@@ -3554,7 +3501,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       for (i=0 ; i < fs_size_x4 ; i++)
       {
 
-        if (img->MbaffFrameFlag && fs->field_frame[j][i])
+        if (img->MbaffFrameFlag && fs->motion.field_frame[j][i])
         {
           //! Assign frame buffers for field MBs
           //! Check whether we should use top or bottom field mvs.
@@ -3562,41 +3509,41 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 
           if (iabs(dec_picture->poc - fs_bottom->poc)> iabs(dec_picture->poc -fs_top->poc) )
           {
-            p->mv[LIST_0][j][i][0]      = fs_top->mv[LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]      = fs_top->mv[LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]      = fs_top->mv[LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]      = fs_top->mv[LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]    = fs_top->ref_idx[LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]    = fs_top->ref_idx[LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj][i];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj][i];
+            p->frame.mv[LIST_0][j][i][0]      = fs_top->motion.mv[LIST_0][jdiv][i][0];
+            p->frame.mv[LIST_0][j][i][1]      = fs_top->motion.mv[LIST_0][jdiv][i][1] ;
+            p->frame.mv[LIST_1][j][i][0]      = fs_top->motion.mv[LIST_1][jdiv][i][0];
+            p->frame.mv[LIST_1][j][i][1]      = fs_top->motion.mv[LIST_1][jdiv][i][1] ;
+            p->frame.ref_idx[LIST_0][j][i]    = fs_top->motion.ref_idx[LIST_0][jdiv][i];
+            p->frame.ref_idx[LIST_1][j][i]    = fs_top->motion.ref_idx[LIST_1][jdiv][i];
+            p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj][i];
+            p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj][i];
 
             p->is_long_term             = fs_top->is_long_term;
           }
           else
           {
-            p->mv[LIST_0][j][i][0]      = fs_bottom->mv[LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]      = fs_bottom->mv[LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]      = fs_bottom->mv[LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]      = fs_bottom->mv[LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]    = fs_bottom->ref_idx[LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]    = fs_bottom->ref_idx[LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj + 4][i];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj + 4][i];
+            p->frame.mv[LIST_0][j][i][0]      = fs_bottom->motion.mv[LIST_0][jdiv][i][0];
+            p->frame.mv[LIST_0][j][i][1]      = fs_bottom->motion.mv[LIST_0][jdiv][i][1] ;
+            p->frame.mv[LIST_1][j][i][0]      = fs_bottom->motion.mv[LIST_1][jdiv][i][0];
+            p->frame.mv[LIST_1][j][i][1]      = fs_bottom->motion.mv[LIST_1][jdiv][i][1] ;
+            p->frame.ref_idx[LIST_0][j][i]    = fs_bottom->motion.ref_idx[LIST_0][jdiv][i];
+            p->frame.ref_idx[LIST_1][j][i]    = fs_bottom->motion.ref_idx[LIST_1][jdiv][i];
+            p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj + 4][i];
+            p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj + 4][i];
 
             p->is_long_term             = fs_bottom->is_long_term;
           }
         }
         else
         {
-          p->mv[LIST_0][j][i][0]      = fs->mv[LIST_0][j][i][0];
-          p->mv[LIST_0][j][i][1]      = fs->mv[LIST_0][j][i][1] ;
-          p->mv[LIST_1][j][i][0]      = fs->mv[LIST_1][j][i][0];
-          p->mv[LIST_1][j][i][1]      = fs->mv[LIST_1][j][i][1] ;
-          p->ref_idx[LIST_0][j][i]    = fs->ref_idx[LIST_0][j][i];
-          p->ref_idx[LIST_1][j][i]    = fs->ref_idx[LIST_1][j][i];
-          p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][j][i];
-          p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][j][i];
+          p->frame.mv[LIST_0][j][i][0]      = fs->motion.mv[LIST_0][j][i][0];
+          p->frame.mv[LIST_0][j][i][1]      = fs->motion.mv[LIST_0][j][i][1] ;
+          p->frame.mv[LIST_1][j][i][0]      = fs->motion.mv[LIST_1][j][i][0];
+          p->frame.mv[LIST_1][j][i][1]      = fs->motion.mv[LIST_1][j][i][1] ;
+          p->frame.ref_idx[LIST_0][j][i]    = fs->motion.ref_idx[LIST_0][j][i];
+          p->frame.ref_idx[LIST_1][j][i]    = fs->motion.ref_idx[LIST_1][j][i];
+          p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][j][i];
+          p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][j][i];
 
           p->is_long_term             = fs->is_long_term;
         }
@@ -3617,102 +3564,102 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         //! Do nothing if macroblock as field coded in MB-AFF
         if (!img->MbaffFrameFlag )
         {
-          p->mv[LIST_0][j][i][0] = fs->mv[LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1] = fs->mv[LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0] = fs->mv[LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1] = fs->mv[LIST_1][jj][ii][1];
+          p->frame.mv[LIST_0][j][i][0] = fs->motion.mv[LIST_0][jj][ii][0];
+          p->frame.mv[LIST_0][j][i][1] = fs->motion.mv[LIST_0][jj][ii][1];
+          p->frame.mv[LIST_1][j][i][0] = fs->motion.mv[LIST_1][jj][ii][0];
+          p->frame.mv[LIST_1][j][i][1] = fs->motion.mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
 
-          if (fs->ref_idx[LIST_0][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_0][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_0][j][i] = -1;
-            p->ref_pic_id[LIST_0][j][i] = -1;
+            p->frame.ref_idx   [LIST_0][j][i] = -1;
+            p->frame.ref_pic_id[LIST_0][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_0][j][i] = fs->ref_idx[LIST_0][jj][ii] ;
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id [LIST_0][jj][ii];
+            p->frame.ref_idx   [LIST_0][j][i] = fs->motion.ref_idx[LIST_0][jj][ii] ;
+            p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id [LIST_0][jj][ii];
           }
 
-          if (fs->ref_idx[LIST_1][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_1][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_1][j][i] = -1;
-            p->ref_pic_id[LIST_1][j][i] = -1;
+            p->frame.ref_idx   [LIST_1][j][i] = -1;
+            p->frame.ref_pic_id[LIST_1][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_1][j][i] = fs->ref_idx[LIST_1][jj][ii];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id [LIST_1][jj][ii];
+            p->frame.ref_idx   [LIST_1][j][i] = fs->motion.ref_idx[LIST_1][jj][ii];
+            p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id [LIST_1][jj][ii];
           }
 
           p->is_long_term = fs->is_long_term;
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->moving_block[j][i] =
+            p->frame.moving_block[j][i] =
               !((!p->is_long_term
-              && ((p->ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->ref_idx[LIST_0][j][i] == -1)
-              &&  (p->ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0)));
           }
         }
         else
         {
-          p->bottom_mv[LIST_0][j][i][0] = fs_bottom->mv[LIST_0][jj][ii][0];
-          p->bottom_mv[LIST_0][j][i][1] = fs_bottom->mv[LIST_0][jj][ii][1];
-          p->bottom_mv[LIST_1][j][i][0] = fs_bottom->mv[LIST_1][jj][ii][0];
-          p->bottom_mv[LIST_1][j][i][1] = fs_bottom->mv[LIST_1][jj][ii][1];
-          p->bottom_ref_idx[LIST_0][j][i] = fs_bottom->ref_idx[LIST_0][jj][ii];
-          p->bottom_ref_idx[LIST_1][j][i] = fs_bottom->ref_idx[LIST_1][jj][ii];
-          p->bottom_ref_pic_id[LIST_0][j][i] = fs_bottom->ref_id[LIST_0][jj][ii];
-          p->bottom_ref_pic_id[LIST_1][j][i] = fs_bottom->ref_id[LIST_1][jj][ii];
+          p->bottom.mv[LIST_0][j][i][0] = fs_bottom->motion.mv[LIST_0][jj][ii][0];
+          p->bottom.mv[LIST_0][j][i][1] = fs_bottom->motion.mv[LIST_0][jj][ii][1];
+          p->bottom.mv[LIST_1][j][i][0] = fs_bottom->motion.mv[LIST_1][jj][ii][0];
+          p->bottom.mv[LIST_1][j][i][1] = fs_bottom->motion.mv[LIST_1][jj][ii][1];
+          p->bottom.ref_idx[LIST_0][j][i] = fs_bottom->motion.ref_idx[LIST_0][jj][ii];
+          p->bottom.ref_idx[LIST_1][j][i] = fs_bottom->motion.ref_idx[LIST_1][jj][ii];
+          p->bottom.ref_pic_id[LIST_0][j][i] = fs_bottom->motion.ref_id[LIST_0][jj][ii];
+          p->bottom.ref_pic_id[LIST_1][j][i] = fs_bottom->motion.ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->bottom_moving_block[j][i] =
+            p->bottom.moving_block[j][i] =
               !((!fs_bottom->is_long_term
-              && ((p->bottom_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->bottom_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->bottom_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->bottom.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->bottom.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->bottom.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          p->top_mv[LIST_0][j][i][0] = fs_top->mv[LIST_0][jj][ii][0];
-          p->top_mv[LIST_0][j][i][1] = fs_top->mv[LIST_0][jj][ii][1];
-          p->top_mv[LIST_1][j][i][0] = fs_top->mv[LIST_1][jj][ii][0];
-          p->top_mv[LIST_1][j][i][1] = fs_top->mv[LIST_1][jj][ii][1];
-          p->top_ref_idx[LIST_0][j][i] = fs_top->ref_idx[LIST_0][jj][ii];
-          p->top_ref_idx[LIST_1][j][i] = fs_top->ref_idx[LIST_1][jj][ii];
-          p->top_ref_pic_id[LIST_0][j][i] = fs_top->ref_id[LIST_0][jj][ii];
-          p->top_ref_pic_id[LIST_1][j][i] = fs_top->ref_id[LIST_1][jj][ii];
+          p->top.mv[LIST_0][j][i][0] = fs_top->motion.mv[LIST_0][jj][ii][0];
+          p->top.mv[LIST_0][j][i][1] = fs_top->motion.mv[LIST_0][jj][ii][1];
+          p->top.mv[LIST_1][j][i][0] = fs_top->motion.mv[LIST_1][jj][ii][0];
+          p->top.mv[LIST_1][j][i][1] = fs_top->motion.mv[LIST_1][jj][ii][1];
+          p->top.ref_idx[LIST_0][j][i] = fs_top->motion.ref_idx[LIST_0][jj][ii];
+          p->top.ref_idx[LIST_1][j][i] = fs_top->motion.ref_idx[LIST_1][jj][ii];
+          p->top.ref_pic_id[LIST_0][j][i] = fs_top->motion.ref_id[LIST_0][jj][ii];
+          p->top.ref_pic_id[LIST_1][j][i] = fs_top->motion.ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->top_moving_block[j][i] =
+            p->top.moving_block[j][i] =
               !((!fs_top->is_long_term
-              && ((p->top_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->top_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->top_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->top.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->top.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->top.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->field_frame[2*j][i])
+          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->motion.field_frame[2*j][i])
           {
-            p->top_mv[LIST_0][j][i][1] /= 2;
-            p->top_mv[LIST_1][j][i][1] /= 2;
-            p->bottom_mv[LIST_0][j][i][1] /= 2;
-            p->bottom_mv[LIST_1][j][i][1] /= 2;
+            p->top.mv[LIST_0][j][i][1] /= 2;
+            p->top.mv[LIST_1][j][i][1] /= 2;
+            p->bottom.mv[LIST_0][j][i][1] /= 2;
+            p->bottom.mv[LIST_1][j][i][1] /= 2;
           }
 
         }
@@ -3735,32 +3682,32 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         for (i = 0 ; i < fs_size_x4; i++)
         {
 
-          if (fs->field_frame[j][i])
+          if (fs->motion.field_frame[j][i])
           {
             if (iabs(dec_picture->poc - fs->bottom_field->poc) > iabs(dec_picture->poc - fs->top_field->poc))
             {
-              p->mv[LIST_0][j][i][0] = fs->top_field->mv[LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->top_field->mv[LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->top_field->mv[LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->top_field->mv[LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]    = fs->top_field->ref_idx[LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]    = fs->top_field->ref_idx[LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj][i];
-              p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj][i];
+              p->frame.mv[LIST_0][j][i][0] = fs->top_field->motion.mv[LIST_0][jdiv][i][0];
+              p->frame.mv[LIST_0][j][i][1] = fs->top_field->motion.mv[LIST_0][jdiv][i][1] ;
+              p->frame.mv[LIST_1][j][i][0] = fs->top_field->motion.mv[LIST_1][jdiv][i][0];
+              p->frame.mv[LIST_1][j][i][1] = fs->top_field->motion.mv[LIST_1][jdiv][i][1] ;
+
+              p->frame.ref_idx[LIST_0][j][i]    = fs->top_field->motion.ref_idx[LIST_0][jdiv][i];
+              p->frame.ref_idx[LIST_1][j][i]    = fs->top_field->motion.ref_idx[LIST_1][jdiv][i];
+              p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj][i];
+              p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj][i];
               p->is_long_term             = fs->top_field->is_long_term;
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = fs->bottom_field->mv[LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->bottom_field->mv[LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->bottom_field->mv[LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->bottom_field->mv[LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->bottom_field->ref_idx[LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->bottom_field->ref_idx[LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj + 4][i];
-              p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj + 4][i];
+              p->frame.mv[LIST_0][j][i][0] = fs->bottom_field->motion.mv[LIST_0][jdiv][i][0];
+              p->frame.mv[LIST_0][j][i][1] = fs->bottom_field->motion.mv[LIST_0][jdiv][i][1] ;
+              p->frame.mv[LIST_1][j][i][0] = fs->bottom_field->motion.mv[LIST_1][jdiv][i][0];
+              p->frame.mv[LIST_1][j][i][1] = fs->bottom_field->motion.mv[LIST_1][jdiv][i][1] ;
+
+              p->frame.ref_idx[LIST_0][j][i]  = fs->bottom_field->motion.ref_idx[LIST_0][jdiv][i];
+              p->frame.ref_idx[LIST_1][j][i]  = fs->bottom_field->motion.ref_idx[LIST_1][jdiv][i];
+              p->frame.ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj + 4][i];
+              p->frame.ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj + 4][i];
               p->is_long_term             = fs->bottom_field->is_long_term;
             }
           }
@@ -3783,25 +3730,25 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         {
           ii = RSD(i);
 
-          p->mv[LIST_0][j][i][0]=p->mv[LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1]=p->mv[LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0]=p->mv[LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1]=p->mv[LIST_1][jj][ii][1];
+          p->frame.mv[LIST_0][j][i][0]=p->frame.mv[LIST_0][jj][ii][0];
+          p->frame.mv[LIST_0][j][i][1]=p->frame.mv[LIST_0][jj][ii][1];
+          p->frame.mv[LIST_1][j][i][0]=p->frame.mv[LIST_1][jj][ii][0];
+          p->frame.mv[LIST_1][j][i][1]=p->frame.mv[LIST_1][jj][ii][1];
 
-          p->ref_idx[LIST_0][j][i]=p->ref_idx[LIST_0][jj][ii];
-          p->ref_idx[LIST_1][j][i]=p->ref_idx[LIST_1][jj][ii];
-          p->ref_pic_id[LIST_0][j][i] = p->ref_pic_id[LIST_0][jj][ii];
-          p->ref_pic_id[LIST_1][j][i] = p->ref_pic_id[LIST_1][jj][ii];
+          p->frame.ref_idx[LIST_0][j][i]=p->frame.ref_idx[LIST_0][jj][ii];
+          p->frame.ref_idx[LIST_1][j][i]=p->frame.ref_idx[LIST_1][jj][ii];
+          p->frame.ref_pic_id[LIST_0][j][i] = p->frame.ref_pic_id[LIST_0][jj][ii];
+          p->frame.ref_pic_id[LIST_1][j][i] = p->frame.ref_pic_id[LIST_1][jj][ii];
 
-          p->moving_block[j][i]=
+          p->frame.moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+            &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
@@ -3814,15 +3761,15 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         {
           ii = RSD(i);
 
-          p->mv[LIST_0][j][i][0]=p->mv[LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1]=p->mv[LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0]=p->mv[LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1]=p->mv[LIST_1][jj][ii][1];
+          p->frame.mv[LIST_0][j][i][0]=p->frame.mv[LIST_0][jj][ii][0];
+          p->frame.mv[LIST_0][j][i][1]=p->frame.mv[LIST_0][jj][ii][1];
+          p->frame.mv[LIST_1][j][i][0]=p->frame.mv[LIST_1][jj][ii][0];
+          p->frame.mv[LIST_1][j][i][1]=p->frame.mv[LIST_1][jj][ii][1];
 
-          p->ref_idx[LIST_0][j][i]=p->ref_idx[LIST_0][jj][ii];
-          p->ref_idx[LIST_1][j][i]=p->ref_idx[LIST_1][jj][ii];
-          p->ref_pic_id[LIST_0][j][i] = p->ref_pic_id[LIST_0][jj][ii];
-          p->ref_pic_id[LIST_1][j][i] = p->ref_pic_id[LIST_1][jj][ii];
+          p->frame.ref_idx[LIST_0][j][i]=p->frame.ref_idx[LIST_0][jj][ii];
+          p->frame.ref_idx[LIST_1][j][i]=p->frame.ref_idx[LIST_1][jj][ii];
+          p->frame.ref_pic_id[LIST_0][j][i] = p->frame.ref_pic_id[LIST_0][jj][ii];
+          p->frame.ref_pic_id[LIST_1][j][i] = p->frame.ref_pic_id[LIST_1][jj][ii];
         }
       }
     }
@@ -3833,24 +3780,24 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
     {
       for (j=0 ; j < fs_size_y4; j++)
       {
-        memcpy(&p->mv[LIST_0][j][0][0], &fs->mv[LIST_0][j][0][0], 2 * fs_size_x4 * sizeof(short));
-        memcpy(&p->mv[LIST_1][j][0][0], &fs->mv[LIST_1][j][0][0], 2 * fs_size_x4 * sizeof(short));
-        memcpy(p->ref_idx[LIST_0][j], fs->ref_idx[LIST_0][j], fs_size_x4 * sizeof(char));
-        memcpy(p->ref_idx[LIST_1][j], fs->ref_idx[LIST_1][j], fs_size_x4 * sizeof(char));
-        memcpy(p->ref_pic_id[LIST_0][j], fs->ref_id[LIST_0][j], fs_size_x4 * sizeof(int64));
-        memcpy(p->ref_pic_id[LIST_1][j], fs->ref_id[LIST_1][j], fs_size_x4 * sizeof(int64));
+        memcpy(&p->frame.mv[LIST_0][j][0][0], &fs->motion.mv[LIST_0][j][0][0], 2 * fs_size_x4 * sizeof(short));
+        memcpy(&p->frame.mv[LIST_1][j][0][0], &fs->motion.mv[LIST_1][j][0][0], 2 * fs_size_x4 * sizeof(short));
+        memcpy(p->frame.ref_idx[LIST_0][j], fs->motion.ref_idx[LIST_0][j], fs_size_x4 * sizeof(char));
+        memcpy(p->frame.ref_idx[LIST_1][j], fs->motion.ref_idx[LIST_1][j], fs_size_x4 * sizeof(char));
+        memcpy(p->frame.ref_pic_id[LIST_0][j], fs->motion.ref_id[LIST_0][j], fs_size_x4 * sizeof(int64));
+        memcpy(p->frame.ref_pic_id[LIST_1][j], fs->motion.ref_id[LIST_1][j], fs_size_x4 * sizeof(int64));
 
         for (i=0 ; i < fs_size_x4; i++)
         {
-          p->moving_block[j][i]=
+          p->frame.moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+            &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
@@ -3858,12 +3805,12 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
     {
       for (j=0 ; j < fs_size_y4; j++)
       {
-        memcpy(&p->mv[LIST_0][j][0][0], &fs->mv[LIST_0][j][0][0], 2 * fs_size_x4 * sizeof(short));
-        memcpy(&p->mv[LIST_1][j][0][0], &fs->mv[LIST_1][j][0][0], 2 * fs_size_x4 * sizeof(short));
-        memcpy(p->ref_idx[LIST_0][j], fs->ref_idx[LIST_0][j], fs_size_x4 * sizeof(char));
-        memcpy(p->ref_idx[LIST_1][j], fs->ref_idx[LIST_1][j], fs_size_x4 * sizeof(char));
-        memcpy(p->ref_pic_id[LIST_0][j], fs->ref_id[LIST_0][j], fs_size_x4 * sizeof(int64));
-        memcpy(p->ref_pic_id[LIST_1][j], fs->ref_id[LIST_1][j], fs_size_x4 * sizeof(int64));   
+        memcpy(&p->frame.mv[LIST_0][j][0][0], &fs->motion.mv[LIST_0][j][0][0], 2 * fs_size_x4 * sizeof(short));
+        memcpy(&p->frame.mv[LIST_1][j][0][0], &fs->motion.mv[LIST_1][j][0][0], 2 * fs_size_x4 * sizeof(short));
+        memcpy(p->frame.ref_idx[LIST_0][j], fs->motion.ref_idx[LIST_0][j], fs_size_x4 * sizeof(char));
+        memcpy(p->frame.ref_idx[LIST_1][j], fs->motion.ref_idx[LIST_1][j], fs_size_x4 * sizeof(char));
+        memcpy(p->frame.ref_pic_id[LIST_0][j], fs->motion.ref_id[LIST_0][j], fs_size_x4 * sizeof(int64));
+        memcpy(p->frame.ref_pic_id[LIST_1][j], fs->motion.ref_id[LIST_1][j], fs_size_x4 * sizeof(int64));   
       }
     }
   }
@@ -3876,10 +3823,10 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       {
         for (i=0 ; i < fs_size_x4 ; i++)
         {
-          if (fs->field_frame[j][i])
+          if (fs->motion.field_frame[j][i])
           {
-            p->mv[LIST_0][j][i][1] *= 2;
-            p->mv[LIST_1][j][i][1] *= 2;
+            p->frame.mv[LIST_0][j][i][1] *= 2;
+            p->frame.mv[LIST_1][j][i][1] *= 2;
           }
         }
       }
@@ -3890,10 +3837,10 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       {
         for (i=0 ; i < fs_size_x4 ; i++)
         {
-          if (!fs->field_frame[j][i])
+          if (!fs->motion.field_frame[j][i])
           {
-            p->mv[LIST_0][j][i][1] /= 2;
-            p->mv[LIST_1][j][i][1] /= 2;
+            p->frame.mv[LIST_0][j][i][1] /= 2;
+            p->frame.mv[LIST_1][j][i][1] /= 2;
           }
         }
       }
@@ -3949,7 +3896,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
   int i,j, ii, jj, jdiv;
   int np = img->colour_plane_id;
 
-  fs_top=fs_bottom=fs = listX[LIST_1 ][0];
+  fs_top = fs_bottom = fs = listX[LIST_1 ][0];
 
   if (img->MbaffFrameFlag)
   {
@@ -3983,7 +3930,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
 
-        if (img->MbaffFrameFlag && fs->field_frame[j][i])
+        if (img->MbaffFrameFlag && fs->motion.field_frame[j][i])
         {
           //! Assign frame buffers for field MBs
           //! Check whether we should use top or bottom field mvs.
@@ -3991,41 +3938,41 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
           if (iabs(dec_picture->poc - fs_bottom->poc)> iabs(dec_picture->poc -fs_top->poc) )
           {
-            p->mv[LIST_0][j][i][0]    = fs_top->mv_JV[np][LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]    = fs_top->mv_JV[np][LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]    = fs_top->mv_JV[np][LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]    = fs_top->mv_JV[np][LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]  = fs_top->ref_idx_JV[np][LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]  = fs_top->ref_idx_JV[np][LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i]   = fs->ref_id_JV[np][LIST_0][jj][i];
-            p->ref_pic_id[LIST_1][j][i]   = fs->ref_id_JV[np][LIST_1][jj][i];
+            p->frame.mv[LIST_0][j][i][0]    = fs_top->JVmotion[np].mv[LIST_0][jdiv][i][0];
+            p->frame.mv[LIST_0][j][i][1]    = fs_top->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+            p->frame.mv[LIST_1][j][i][0]    = fs_top->JVmotion[np].mv[LIST_1][jdiv][i][0];
+            p->frame.mv[LIST_1][j][i][1]    = fs_top->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+            p->frame.ref_idx[LIST_0][j][i]  = fs_top->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+            p->frame.ref_idx[LIST_1][j][i]  = fs_top->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+            p->frame.ref_pic_id[LIST_0][j][i]   = fs->JVmotion[np].ref_id[LIST_0][jj][i];
+            p->frame.ref_pic_id[LIST_1][j][i]   = fs->JVmotion[np].ref_id[LIST_1][jj][i];
 
             p->is_long_term             = fs_top->is_long_term;
           }
           else
           {
-            p->mv[LIST_0][j][i][0]      = fs_bottom->mv_JV[np][LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]      = fs_bottom->mv_JV[np][LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]      = fs_bottom->mv_JV[np][LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]      = fs_bottom->mv_JV[np][LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]    = fs_bottom->ref_idx_JV[np][LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]    = fs_bottom->ref_idx_JV[np][LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][jj + 4][i];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][jj + 4][i];
+            p->frame.mv[LIST_0][j][i][0]      = fs_bottom->JVmotion[np].mv[LIST_0][jdiv][i][0];
+            p->frame.mv[LIST_0][j][i][1]      = fs_bottom->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+            p->frame.mv[LIST_1][j][i][0]      = fs_bottom->JVmotion[np].mv[LIST_1][jdiv][i][0];
+            p->frame.mv[LIST_1][j][i][1]      = fs_bottom->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+            p->frame.ref_idx[LIST_0][j][i]    = fs_bottom->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+            p->frame.ref_idx[LIST_1][j][i]    = fs_bottom->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+            p->frame.ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][jj + 4][i];
+            p->frame.ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][jj + 4][i];
 
             p->is_long_term             = fs_bottom->is_long_term;
           }
         }
         else
         {
-          p->mv[LIST_0][j][i][0]      = fs->mv_JV[np][LIST_0][j][i][0];
-          p->mv[LIST_0][j][i][1]      = fs->mv_JV[np][LIST_0][j][i][1] ;
-          p->mv[LIST_1][j][i][0]      = fs->mv_JV[np][LIST_1][j][i][0];
-          p->mv[LIST_1][j][i][1]      = fs->mv_JV[np][LIST_1][j][i][1] ;
-          p->ref_idx[LIST_0][j][i]    = fs->ref_idx_JV[np][LIST_0][j][i];
-          p->ref_idx[LIST_1][j][i]    = fs->ref_idx_JV[np][LIST_1][j][i];
-          p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][j][i];
-          p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][j][i];
+          p->frame.mv[LIST_0][j][i][0]      = fs->JVmotion[np].mv[LIST_0][j][i][0];
+          p->frame.mv[LIST_0][j][i][1]      = fs->JVmotion[np].mv[LIST_0][j][i][1] ;
+          p->frame.mv[LIST_1][j][i][0]      = fs->JVmotion[np].mv[LIST_1][j][i][0];
+          p->frame.mv[LIST_1][j][i][1]      = fs->JVmotion[np].mv[LIST_1][j][i][1] ;
+          p->frame.ref_idx[LIST_0][j][i]    = fs->JVmotion[np].ref_idx[LIST_0][j][i];
+          p->frame.ref_idx[LIST_1][j][i]    = fs->JVmotion[np].ref_idx[LIST_1][j][i];
+          p->frame.ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][j][i];
+          p->frame.ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][j][i];
 
           p->is_long_term             = fs->is_long_term;
         }
@@ -4046,102 +3993,102 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
         //! Do nothing if macroblock as field coded in MB-AFF
         if (!img->MbaffFrameFlag )
         {
-          p->mv[LIST_0][j][i][0] = fs->mv_JV[np][LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1] = fs->mv_JV[np][LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0] = fs->mv_JV[np][LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1] = fs->mv_JV[np][LIST_1][jj][ii][1];
+          p->frame.mv[LIST_0][j][i][0] = fs->JVmotion[np].mv[LIST_0][jj][ii][0];
+          p->frame.mv[LIST_0][j][i][1] = fs->JVmotion[np].mv[LIST_0][jj][ii][1];
+          p->frame.mv[LIST_1][j][i][0] = fs->JVmotion[np].mv[LIST_1][jj][ii][0];
+          p->frame.mv[LIST_1][j][i][1] = fs->JVmotion[np].mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
 
-          if (fs->ref_idx_JV[np][LIST_0][jj][ii] == -1)
+          if (fs->JVmotion[np].ref_idx[LIST_0][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_0][j][i] = -1;
-            p->ref_pic_id[LIST_0][j][i] = -1;
+            p->frame.ref_idx   [LIST_0][j][i] = -1;
+            p->frame.ref_pic_id[LIST_0][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_0][j][i] = fs->ref_idx_JV[np][LIST_0][jj][ii] ;
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np] [LIST_0][jj][ii];
+            p->frame.ref_idx   [LIST_0][j][i] = fs->JVmotion[np].ref_idx[LIST_0][jj][ii] ;
+            p->frame.ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id [LIST_0][jj][ii];
           }
 
-          if (fs->ref_idx_JV[np][LIST_1][jj][ii] == -1)
+          if (fs->JVmotion[np].ref_idx[LIST_1][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_1][j][i] = -1;
-            p->ref_pic_id[LIST_1][j][i] = -1;
+            p->frame.ref_idx   [LIST_1][j][i] = -1;
+            p->frame.ref_pic_id[LIST_1][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_1][j][i] = fs->ref_idx_JV[np][LIST_1][jj][ii];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np] [LIST_1][jj][ii];
+            p->frame.ref_idx   [LIST_1][j][i] = fs->JVmotion[np].ref_idx[LIST_1][jj][ii];
+            p->frame.ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id [LIST_1][jj][ii];
           }
 
           p->is_long_term = fs->is_long_term;
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->moving_block[j][i] =
+            p->frame.moving_block[j][i] =
               !((!p->is_long_term
-              && ((p->ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->ref_idx[LIST_0][j][i] == -1)
-              &&  (p->ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0)));
           }
         }
         else
         {
-          p->bottom_mv[LIST_0][j][i][0] = fs_bottom->mv_JV[np][LIST_0][jj][ii][0];
-          p->bottom_mv[LIST_0][j][i][1] = fs_bottom->mv_JV[np][LIST_0][jj][ii][1];
-          p->bottom_mv[LIST_1][j][i][0] = fs_bottom->mv_JV[np][LIST_1][jj][ii][0];
-          p->bottom_mv[LIST_1][j][i][1] = fs_bottom->mv_JV[np][LIST_1][jj][ii][1];
-          p->bottom_ref_idx[LIST_0][j][i] = fs_bottom->ref_idx_JV[np][LIST_0][jj][ii];
-          p->bottom_ref_idx[LIST_1][j][i] = fs_bottom->ref_idx_JV[np][LIST_1][jj][ii];
-          p->bottom_ref_pic_id[LIST_0][j][i] = fs_bottom->ref_id_JV[np][LIST_0][jj][ii];
-          p->bottom_ref_pic_id[LIST_1][j][i] = fs_bottom->ref_id_JV[np][LIST_1][jj][ii];
+          p->bottom.mv[LIST_0][j][i][0] = fs_bottom->JVmotion[np].mv[LIST_0][jj][ii][0];
+          p->bottom.mv[LIST_0][j][i][1] = fs_bottom->JVmotion[np].mv[LIST_0][jj][ii][1];
+          p->bottom.mv[LIST_1][j][i][0] = fs_bottom->JVmotion[np].mv[LIST_1][jj][ii][0];
+          p->bottom.mv[LIST_1][j][i][1] = fs_bottom->JVmotion[np].mv[LIST_1][jj][ii][1];
+          p->bottom.ref_idx[LIST_0][j][i] = fs_bottom->JVmotion[np].ref_idx[LIST_0][jj][ii];
+          p->bottom.ref_idx[LIST_1][j][i] = fs_bottom->JVmotion[np].ref_idx[LIST_1][jj][ii];
+          p->bottom.ref_pic_id[LIST_0][j][i] = fs_bottom->JVmotion[np].ref_id[LIST_0][jj][ii];
+          p->bottom.ref_pic_id[LIST_1][j][i] = fs_bottom->JVmotion[np].ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->bottom_moving_block[j][i] =
+            p->bottom.moving_block[j][i] =
               !((!fs_bottom->is_long_term
-              && ((p->bottom_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->bottom_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->bottom_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->bottom.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->bottom.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->bottom.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          p->top_mv[LIST_0][j][i][0] = fs_top->mv_JV[np][LIST_0][jj][ii][0];
-          p->top_mv[LIST_0][j][i][1] = fs_top->mv_JV[np][LIST_0][jj][ii][1];
-          p->top_mv[LIST_1][j][i][0] = fs_top->mv_JV[np][LIST_1][jj][ii][0];
-          p->top_mv[LIST_1][j][i][1] = fs_top->mv_JV[np][LIST_1][jj][ii][1];
-          p->top_ref_idx[LIST_0][j][i] = fs_top->ref_idx_JV[np][LIST_0][jj][ii];
-          p->top_ref_idx[LIST_1][j][i] = fs_top->ref_idx_JV[np][LIST_1][jj][ii];
-          p->top_ref_pic_id[LIST_0][j][i] = fs_top->ref_id_JV[np][LIST_0][jj][ii];
-          p->top_ref_pic_id[LIST_1][j][i] = fs_top->ref_id_JV[np][LIST_1][jj][ii];
+          p->top.mv[LIST_0][j][i][0] = fs_top->JVmotion[np].mv[LIST_0][jj][ii][0];
+          p->top.mv[LIST_0][j][i][1] = fs_top->JVmotion[np].mv[LIST_0][jj][ii][1];
+          p->top.mv[LIST_1][j][i][0] = fs_top->JVmotion[np].mv[LIST_1][jj][ii][0];
+          p->top.mv[LIST_1][j][i][1] = fs_top->JVmotion[np].mv[LIST_1][jj][ii][1];
+          p->top.ref_idx[LIST_0][j][i] = fs_top->JVmotion[np].ref_idx[LIST_0][jj][ii];
+          p->top.ref_idx[LIST_1][j][i] = fs_top->JVmotion[np].ref_idx[LIST_1][jj][ii];
+          p->top.ref_pic_id[LIST_0][j][i] = fs_top->JVmotion[np].ref_id[LIST_0][jj][ii];
+          p->top.ref_pic_id[LIST_1][j][i] = fs_top->JVmotion[np].ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->top_moving_block[j][i] =
+            p->top.moving_block[j][i] =
               !((!fs_top->is_long_term
-              && ((p->top_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->top_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->top_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->top.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->top.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->top.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->field_frame[2*j][i])
+          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->motion.field_frame[2*j][i])
           {
-            p->top_mv[LIST_0][j][i][1] /= 2;
-            p->top_mv[LIST_1][j][i][1] /= 2;
-            p->bottom_mv[LIST_0][j][i][1] /= 2;
-            p->bottom_mv[LIST_1][j][i][1] /= 2;
+            p->top.mv[LIST_0][j][i][1] /= 2;
+            p->top.mv[LIST_1][j][i][1] /= 2;
+            p->bottom.mv[LIST_0][j][i][1] /= 2;
+            p->bottom.mv[LIST_1][j][i][1] /= 2;
           }
 
         }
@@ -4164,32 +4111,32 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
         for (i=0 ; i<fs->size_x/4 ; i++)
         {
 
-          if (fs->field_frame[j][i])
+          if (fs->motion.field_frame[j][i])
           {
             if (iabs(dec_picture->poc - fs->bottom_field->poc) > iabs(dec_picture->poc - fs->top_field->poc))
             {
-              p->mv[LIST_0][j][i][0] = fs->top_field->mv_JV[np][LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->top_field->mv_JV[np][LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->top_field->mv_JV[np][LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->top_field->mv_JV[np][LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->top_field->ref_idx_JV[np][LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->top_field->ref_idx_JV[np][LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i]   = fs->ref_id_JV[np][LIST_0][jj][i];
-              p->ref_pic_id[LIST_1][j][i]   = fs->ref_id_JV[np][LIST_1][jj][i];
+              p->frame.mv[LIST_0][j][i][0] = fs->top_field->JVmotion[np].mv[LIST_0][jdiv][i][0];
+              p->frame.mv[LIST_0][j][i][1] = fs->top_field->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+              p->frame.mv[LIST_1][j][i][0] = fs->top_field->JVmotion[np].mv[LIST_1][jdiv][i][0];
+              p->frame.mv[LIST_1][j][i][1] = fs->top_field->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+
+              p->frame.ref_idx[LIST_0][j][i]  = fs->top_field->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+              p->frame.ref_idx[LIST_1][j][i]  = fs->top_field->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+              p->frame.ref_pic_id[LIST_0][j][i]   = fs->JVmotion[np].ref_id[LIST_0][jj][i];
+              p->frame.ref_pic_id[LIST_1][j][i]   = fs->JVmotion[np].ref_id[LIST_1][jj][i];
               p->is_long_term               = fs->top_field->is_long_term;
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = fs->bottom_field->mv_JV[np][LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->bottom_field->mv_JV[np][LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->bottom_field->mv_JV[np][LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->bottom_field->mv_JV[np][LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->bottom_field->ref_idx_JV[np][LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->bottom_field->ref_idx_JV[np][LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][jj + 4][i];
-              p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][jj + 4][i];
+              p->frame.mv[LIST_0][j][i][0] = fs->bottom_field->JVmotion[np].mv[LIST_0][jdiv][i][0];
+              p->frame.mv[LIST_0][j][i][1] = fs->bottom_field->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+              p->frame.mv[LIST_1][j][i][0] = fs->bottom_field->JVmotion[np].mv[LIST_1][jdiv][i][0];
+              p->frame.mv[LIST_1][j][i][1] = fs->bottom_field->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+
+              p->frame.ref_idx[LIST_0][j][i]  = fs->bottom_field->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+              p->frame.ref_idx[LIST_1][j][i]  = fs->bottom_field->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+              p->frame.ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][jj + 4][i];
+              p->frame.ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][jj + 4][i];
               p->is_long_term             = fs->bottom_field->is_long_term;
             }
           }
@@ -4209,27 +4156,27 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
 
-        p->mv[LIST_0][j][i][0] = p->mv[LIST_0][jj][ii][0];
-        p->mv[LIST_0][j][i][1] = p->mv[LIST_0][jj][ii][1];
-        p->mv[LIST_1][j][i][0] = p->mv[LIST_1][jj][ii][0];
-        p->mv[LIST_1][j][i][1] = p->mv[LIST_1][jj][ii][1];
+        p->frame.mv[LIST_0][j][i][0] = p->frame.mv[LIST_0][jj][ii][0];
+        p->frame.mv[LIST_0][j][i][1] = p->frame.mv[LIST_0][jj][ii][1];
+        p->frame.mv[LIST_1][j][i][0] = p->frame.mv[LIST_1][jj][ii][0];
+        p->frame.mv[LIST_1][j][i][1] = p->frame.mv[LIST_1][jj][ii][1];
 
-        p->ref_idx[LIST_0][j][i]=p->ref_idx[LIST_0][jj][ii];
-        p->ref_idx[LIST_1][j][i]=p->ref_idx[LIST_1][jj][ii];
-        p->ref_pic_id[LIST_0][j][i] = p->ref_pic_id[LIST_0][jj][ii];
-        p->ref_pic_id[LIST_1][j][i] = p->ref_pic_id[LIST_1][jj][ii];
+        p->frame.ref_idx[LIST_0][j][i]=p->frame.ref_idx[LIST_0][jj][ii];
+        p->frame.ref_idx[LIST_1][j][i]=p->frame.ref_idx[LIST_1][jj][ii];
+        p->frame.ref_pic_id[LIST_0][j][i] = p->frame.ref_pic_id[LIST_0][jj][ii];
+        p->frame.ref_pic_id[LIST_1][j][i] = p->frame.ref_pic_id[LIST_1][jj][ii];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]= (byte) (
+          p->frame.moving_block[j][i]= (byte) (
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0))));
+            && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+            &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0))));
         }
       }
     }
@@ -4243,27 +4190,27 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
         //! Use inference flag to remap mvs/references
-        p->mv[LIST_0][j][i][0]=fs->mv_JV[np][LIST_0][j][i][0];
-        p->mv[LIST_0][j][i][1]=fs->mv_JV[np][LIST_0][j][i][1];
-        p->mv[LIST_1][j][i][0]=fs->mv_JV[np][LIST_1][j][i][0];
-        p->mv[LIST_1][j][i][1]=fs->mv_JV[np][LIST_1][j][i][1];
+        p->frame.mv[LIST_0][j][i][0] = fs->JVmotion[np].mv[LIST_0][j][i][0];
+        p->frame.mv[LIST_0][j][i][1] = fs->JVmotion[np].mv[LIST_0][j][i][1];
+        p->frame.mv[LIST_1][j][i][0] = fs->JVmotion[np].mv[LIST_1][j][i][0];
+        p->frame.mv[LIST_1][j][i][1] = fs->JVmotion[np].mv[LIST_1][j][i][1];
 
-        p->ref_idx[LIST_0][j][i]=fs->ref_idx_JV[np][LIST_0][j][i];
-        p->ref_idx[LIST_1][j][i]=fs->ref_idx_JV[np][LIST_1][j][i];
-        p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][j][i];
-        p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][j][i];
+        p->frame.ref_idx[LIST_0][j][i] = fs->JVmotion[np].ref_idx[LIST_0][j][i];
+        p->frame.ref_idx[LIST_1][j][i] = fs->JVmotion[np].ref_idx[LIST_1][j][i];
+        p->frame.ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][j][i];
+        p->frame.ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][j][i];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]= (byte) (
+          p->frame.moving_block[j][i]= (byte) (
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0))));
+            && ((p->frame.ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((p->frame.ref_idx[LIST_0][j][i] == -1)
+            &&  (p->frame.ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(p->frame.mv[LIST_1][j][i][1])>>1 == 0))));
         }
       }
     }
@@ -4276,15 +4223,15 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
     {
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
-        if ((!img->MbaffFrameFlag &&!img->structure && fs->field_frame[j][i]) || (img->MbaffFrameFlag && fs->field_frame[j][i]))
+        if ((!img->MbaffFrameFlag &&!img->structure && fs->motion.field_frame[j][i]) || (img->MbaffFrameFlag && fs->motion.field_frame[j][i]))
         {
-          p->mv[LIST_0][j][i][1] *= 2;
-          p->mv[LIST_1][j][i][1] *= 2;
+          p->frame.mv[LIST_0][j][i][1] *= 2;
+          p->frame.mv[LIST_1][j][i][1] *= 2;
         }
-        else  if (img->structure && !fs->field_frame[j][i])
+        else  if (img->structure && !fs->motion.field_frame[j][i])
         {
-          p->mv[LIST_0][j][i][1] /= 2;
-          p->mv[LIST_1][j][i][1] /= 2;
+          p->frame.mv[LIST_0][j][i][1] /= 2;
+          p->frame.mv[LIST_1][j][i][1] /= 2;
         }
 
       }
@@ -4325,46 +4272,17 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
   }
 }
 
-void copy_storable_param_JV( int nplane, StorablePicture *d, StorablePicture *s )
+void copy_storable_param_JV( PicMotionParams *JVplane, PicMotionParams *motion )
 {
-  int np, ny, nx;
-
   // copy ref_idx
-  for( np=0; np<2; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_idx_JV[nplane][np][ny], s->ref_idx[np][ny], sizeof(byte)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  memcpy( JVplane->ref_idx[0][0], motion->ref_idx[0][0], 2 * (img->height / BLOCK_SIZE) * (img->width / BLOCK_SIZE) * sizeof(byte));
 
   // copy ref_pic_id
-  for( np=0; np<6; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_pic_id_JV[nplane][np][ny], s->ref_pic_id[np][ny], sizeof(int64)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  memcpy( JVplane->ref_pic_id[0][0], motion->ref_pic_id[0][0], 6 * (img->height / BLOCK_SIZE) * (img->width / BLOCK_SIZE) * sizeof(int64));
 
-  // copy ref_id
-  for( np=0; np<6; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_id_JV[nplane][np][ny], s->ref_id[np][ny], sizeof(int64)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  // copy motion.ref_id
+  memcpy( JVplane->ref_id[0][0], motion->ref_id[0][0], 6 * (img->height / BLOCK_SIZE) * (img->width / BLOCK_SIZE) * sizeof(int64));
 
   // copy mv
-  for( np=0; np<2; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      for( nx=0; nx<img->width/BLOCK_SIZE; nx++ )
-      {
-        memcpy( d->mv_JV[nplane][np][ny][nx], s->mv[np][ny][nx], sizeof(short)*2 );
-      }
-    }
-  }
+  memcpy( JVplane->mv[0][0][0], motion->mv[0][0][0], 2 * (img->height / BLOCK_SIZE) * (img->width / BLOCK_SIZE) * 2 * sizeof(short) );
 }
diff --git a/ldecod/src/mc_prediction.c b/ldecod/src/mc_prediction.c
index 56bdf26..7ca5722 100644
--- a/ldecod/src/mc_prediction.c
+++ b/ldecod/src/mc_prediction.c
@@ -18,10 +18,9 @@
 #include "mc_prediction.h"
 #include "mbuffer.h"
 #include "mb_access.h"
+#include "macroblock.h"
 
 extern StorablePicture *no_reference_picture;
-extern const unsigned char subblk_offset_y[3][8][4];
-extern const unsigned char subblk_offset_x[3][8][4];
 
 imgpel tmp_block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE];     //!< l0 prediction
 imgpel tmp_block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE];     //!< l1 prediction
@@ -33,7 +32,7 @@ static const int COEF[6] = { 1, -5, 20, 20, -5, 1 };
  *    block single list prediction
  ************************************************************************
  */
-static inline void mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+static inline void mc_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
                     int ver_block_size, 
                     int hor_block_size,
                     int ioff,
@@ -43,13 +42,13 @@ static inline void mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
 
   if (hor_block_size == MB_BLOCK_SIZE)
   {
-    memcpy(&(curr_mpr[0][ioff]), &(block[0][0]), hor_block_size * ver_block_size * sizeof(imgpel));
+    memcpy(&(mb_pred[0][ioff]), &(block[0][0]), hor_block_size * ver_block_size * sizeof(imgpel));
   }
   else
   {
     for(jj = 0; jj < ver_block_size; jj++)
     {
-      memcpy(&(curr_mpr[jj][ioff]), &(block[jj][0]), hor_block_size * sizeof(imgpel));
+      memcpy(&(mb_pred[jj][ioff]), &(block[jj][0]), hor_block_size * sizeof(imgpel));
     }
   }
 }
@@ -60,7 +59,7 @@ static inline void mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
  *    block single list weighted prediction
  ************************************************************************
  */
-static inline void weighted_mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+static inline void weighted_mc_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
                             int ver_block_size, 
                             int hor_block_size,
                             int ioff,
@@ -75,7 +74,7 @@ static inline void weighted_mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOC
   
   for(jj=0;jj<ver_block_size;jj++)
   {
-    mpr = &curr_mpr[jj][ioff];
+    mpr = &mb_pred[jj][ioff];
     b0 = block[jj];
     for(ii=0;ii<hor_block_size;ii++)
       *(mpr++) = (imgpel) iClip1(color_clip, (rshift_rnd((wp_scale * *(b0++)), weight_denom)  + wp_offset ));
@@ -89,7 +88,7 @@ static inline void weighted_mc_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOC
  *    block biprediction
  ************************************************************************
  */
-static inline void bi_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],  
+static inline void bi_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],  
                                  imgpel block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
                                  imgpel block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
                                  int ver_block_size, 
@@ -101,7 +100,7 @@ static inline void bi_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
 
   for(jj = 0;jj < ver_block_size;jj++)
   {
-    mpr = &curr_mpr[jj][ioff];
+    mpr = &mb_pred[jj][ioff];
     b0 = block_l0[jj];
     b1 = block_l1[jj];
     for(ii = 0; ii < hor_block_size;ii++)
@@ -115,7 +114,7 @@ static inline void bi_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
  *    block weighted biprediction
  ************************************************************************
  */
-static inline void weighted_bi_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
+static inline void weighted_bi_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
                                           imgpel block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
                                           imgpel block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
                                           int ver_block_size, 
@@ -132,7 +131,7 @@ static inline void weighted_bi_prediction(imgpel curr_mpr[MB_BLOCK_SIZE][MB_BLOC
   
   for(jj = 0; jj < ver_block_size; jj++)
   {
-    mpr = &curr_mpr[jj][ioff];    
+    mpr = &mb_pred[jj][ioff];    
     b0  = block_l0[jj];
     b1  = block_l1[jj];
 
@@ -163,9 +162,10 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
   int i, j, jj;
   int shift_x  = dec_picture->size_x;
   int maxold_x = dec_picture->size_x_m1;
-  int maxold_y = (dec_picture->mb_field[img->current_mb_nr]) ? (dec_picture->size_y >> 1) - 1 : dec_picture->size_y_m1;
+  int maxold_y = (dec_picture->motion.mb_field[img->current_mb_nr]) ? (dec_picture->size_y >> 1) - 1 : dec_picture->size_y_m1;
   int result;
   int pres_x;
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
 
 
   if (curr_ref == no_reference_picture && img->framepoc < img->recovery_poc)
@@ -237,7 +237,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(p1++) + *(p4++)) * COEF[1]
                     + (*(p2++) + *(p3++)) * COEF[2];
 
-            *orig_line++ = (imgpel) iClip1(img->max_imgpel_value, ((result + 16)>>5));
+            *orig_line++ = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
           }
         }
 
@@ -273,7 +273,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(p1++) + *(p4++)) * COEF[1]
                     + (*(p2++) + *(p3++)) * COEF[2];
 
-            *orig_line++ = (imgpel) iClip1(img->max_imgpel_value, ((result + 16)>>5));
+            *orig_line++ = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
           }
           p0 = p1 - hor_block_size;
         }
@@ -331,7 +331,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*x1++ + *x4++) * COEF[1]
                     + (*x2++ + *x3++) * COEF[2];
 
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result+512)>>10));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+512)>>10));
           }
         }
 
@@ -344,7 +344,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             orig_line = block[j];
             for (i = 0; i < hor_block_size; i++)
             {
-              *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>> 1);
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>> 1);
               orig_line++;
             }
           }
@@ -387,7 +387,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(x1++) + *(x4++)) * COEF[1]
                     + (*(x2++) + *(x3++)) * COEF[2];
 
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result + 512)>>10));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 512)>>10));
           }
         }
 
@@ -399,7 +399,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             orig_line = block[j];
             for (i = 0; i < hor_block_size; i++)
             {
-              *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((*(tmp_line++) + 16)>>5))+1)>>1);
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16)>>5))+1)>>1);
               orig_line ++;
             }
           }
@@ -426,7 +426,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(p1++) + *(p4++)) * COEF[1]
                     + (*(p2++) + *(p3++)) * COEF[2];
 
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result + 16)>>5));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
           }
         }
 
@@ -446,7 +446,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(p1++) + *(p4++)) * COEF[1]
                     + (*(p2++) + *(p3++)) * COEF[2];
 
-            *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((result + 16) >> 5)) + 1) >> 1);
+            *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((result + 16) >> 5)) + 1) >> 1);
             orig_line++;
           }
           p0 = p1 - hor_block_size ;
@@ -492,7 +492,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             result += (cur_lineY[ipos_m1] + cur_lineY[ipos_p2]) * COEF[1];
             result += (cur_lineY[ipos   ] + cur_lineY[ipos_p1]) * COEF[2];
 
-            block[j][i] = (imgpel) iClip1(img->max_imgpel_value, ((result + 16)>>5));
+            block[j][i] = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
           }
         }
 
@@ -532,7 +532,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             result  = (p0[pres_x] + p5[pres_x]) * COEF[0];
             result += (p1[pres_x] + p4[pres_x]) * COEF[1];
             result += (p2[pres_x] + p3[pres_x]) * COEF[2];
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result+16)>>5));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+16)>>5));
           }
         }
 
@@ -589,7 +589,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*x1++ + *x4++) * COEF[1]
                     + (*x2++ + *x3++) * COEF[2];
 
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result+512)>>10));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+512)>>10));
           }
         }
 
@@ -601,7 +601,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             orig_line = block[j];
             for (i = 0; i < hor_block_size; i++)
             {
-              *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>>1);
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>>1);
               orig_line++;
             }
           }
@@ -649,7 +649,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
                     + (*(x1++) + *(x4++)) * COEF[1]
                     + (*(x2++) + *(x3++)) * COEF[2];
 
-            *(orig_line++) = (imgpel) iClip1(img->max_imgpel_value, ((result + 512)>>10));
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 512)>>10));
           }
         }
 
@@ -661,7 +661,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             orig_line = block[j];            
             for (i = 0; i < hor_block_size; i++)
             {
-              *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((*(tmp_line++) + 16)>>5)) + 1)>> 1);
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16)>>5)) + 1)>> 1);
               orig_line++;
             }
           }
@@ -688,7 +688,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             result += (cur_lineY[ipos_m1] + cur_lineY[ipos_p2]) * COEF[1];
             result += (cur_lineY[ipos   ] + cur_lineY[ipos_p1]) * COEF[2];
 
-            block[j][i] = (imgpel) iClip1(img->max_imgpel_value, ((result+16)>>5));
+            block[j][i] = (imgpel) iClip1(max_imgpel_value, ((result+16)>>5));
           }
         }
 
@@ -714,7 +714,7 @@ void get_block_luma(ColorPlane pl, StorablePicture *curr_ref, int x_pos, int y_p
             result += (p1[pres_x] + p4[pres_x]) * COEF[1];
             result += (p2[pres_x] + p3[pres_x]) * COEF[2];
 
-            *orig_line = (imgpel) ((*orig_line + iClip1(img->max_imgpel_value, ((result+16)>>5)) + 1 ) >> 1);
+            *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((result+16)>>5)) + 1 ) >> 1);
             orig_line++;
           }
         }      
@@ -743,13 +743,14 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
 
   int i, j;
   int maxold_x = dec_picture->size_x_cr_m1;
-  int maxold_y = (dec_picture->mb_field[img->current_mb_nr]) ? (dec_picture->size_y_cr >> 1) - 1 : dec_picture->size_y_cr_m1;
+  int maxold_y = (dec_picture->motion.mb_field[img->current_mb_nr]) ? (dec_picture->size_y_cr >> 1) - 1 : dec_picture->size_y_cr_m1;
   int result;
   
   static imgpel **cur_img, *blk_line;
   static imgpel *cur_line, *cur_line_p1;
   int tmp_pos;
   static int ipos, ipos_p1;
+  int    max_imgpel_value = img->max_imgpel_value_comp[uv + 1];
 
 
   if (curr_ref == no_reference_picture && img->framepoc < img->recovery_poc)
@@ -788,7 +789,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
         for (i = 0; i < hor_block_size; i++)
         {
           result = (w00 * *cur_line++ + w01 * *cur_line_p1++);
-          *(blk_line++) = (imgpel) iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }
     }
@@ -803,7 +804,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
         for (i = 0; i < hor_block_size; i++)
         {
           result = (w00 * *cur_line++ + w10 * *cur_line_p1++);
-          *(blk_line++) = (imgpel) iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }
     }
@@ -819,7 +820,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
         {
           result  = (w00 * *(cur_line++) + w01 * *(cur_line_p1++));
           result += (w10 * *(cur_line  ) + w11 * *(cur_line_p1  ));
-          *(blk_line++) = (imgpel) iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }
     }
@@ -852,7 +853,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
           ipos    = iClip3(0, maxold_x, tmp_pos++);
 
           result = (w00 * cur_line[ipos] + w01 * cur_line_p1[ipos]);
-          *(blk_line++) = (imgpel) iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }      
     }
@@ -870,7 +871,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
           ipos_p1 = iClip3(0, maxold_x, tmp_pos  );
 
           result = (w00 * cur_line[ipos   ] + w10 * cur_line[ipos_p1]);
-          *(blk_line++) = (imgpel)iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel)iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }      
     }
@@ -893,7 +894,7 @@ void get_block_chroma(int uv, StorablePicture *curr_ref, int x_pos, int y_pos, i
             w10 * cur_line   [ipos_p1] +
             w01 * cur_line_p1[ipos   ] +
             w11 * cur_line_p1[ipos_p1]);
-          *(blk_line++) = (imgpel) iClip1(img->max_imgpel_value_uv, rshift_rnd_sf(result, total_scale));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
         }
       }      
     }
@@ -907,7 +908,7 @@ void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int sm
   int (*m7UV)[16], *m7;
   int uv;
   int b8,b4;
-  int ioff, joff, ii, jj, i, j;
+  int ioff, joff, ii, jj;
 
   for(uv = 0; uv < 2; uv++)
   {
@@ -915,8 +916,8 @@ void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int sm
     itrans_4x4 = (!lossless_qpprime) ? itrans4x4 : itrans4x4_ls;
 
     curUV = dec_picture->imgUV[uv];
-    m7UV = img->m7[uv+1];
-    intrapred_chroma(currMB, img, uv);
+    m7UV  = img->mb_rres[uv+1];
+    intrapred_chroma(img, currMB, uv);
 
     if (!smb && (currMB->cbp >> 4))
     {
@@ -927,7 +928,7 @@ void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int sm
           joff = subblk_offset_y[yuv][b8][b4];          
           ioff = subblk_offset_x[yuv][b8][b4];          
 
-          itrans_4x4((ColorPlane) (uv + 1), img, ioff, joff);
+          itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
 
           for(jj=joff; jj<joff + 4;jj++)
           {
@@ -952,7 +953,7 @@ void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int sm
           ioff = subblk_offset_x[yuv][b8][b4];          
 
           for(jj = joff; jj < 4 + joff;jj++)
-            memcpy(&(curUV[img->pix_c_y + jj][img->pix_c_x + ioff]), &(img->mpr[uv + 1][jj][ioff]), BLOCK_SIZE * sizeof(imgpel));
+            memcpy(&(curUV[img->pix_c_y + jj][img->pix_c_x + ioff]), &(img->mb_pred[uv + 1][jj][ioff]), BLOCK_SIZE * sizeof(imgpel));
         }
       }
     }
@@ -960,18 +961,16 @@ void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int sm
     {
       itrans_sp_cr(img, uv);
 
-      for (j = 0; j < 2; j++)
+      for (joff  = 0; joff < 8; joff += 4)
       {
-        joff = j * 4;
-        for(i = 0; i < 2;i++)
-        {
-          ioff = i * 4;          
-          itrans_4x4((ColorPlane) (uv + 1), img, ioff, joff);
+        for(ioff = 0; ioff < 8;ioff+=4)
+        {          
+          itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
 
           for(jj = joff; jj < joff + 4; jj++)
             for(ii = ioff; ii < ioff + 4; ii++)
             {
-              curUV[img->pix_c_y+jj][ii + img->pix_c_x] = (imgpel) img->m7[uv+1][jj][ii];
+              curUV[img->pix_c_y+jj][ii + img->pix_c_x] = (imgpel) img->mb_rres[uv+1][jj][ii];
             }
         }
       }
@@ -993,101 +992,101 @@ void prepare_direct_params(Macroblock *currMB, StorablePicture *dec_picture, Ima
 
   if (!img->MbaffFrameFlag)
   {
-    l0_rFrameL  = (char) (mb_left.available    ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]       : -1);
-    l0_rFrameU  = (char) (mb_up.available      ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x]           : -1);
-    l0_rFrameUL = (char) (mb_upleft.available  ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
-    l0_rFrameUR = (char) (mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
-
-    l1_rFrameL  = (char) (mb_left.available     ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]      : -1);
-    l1_rFrameU  = (char) (mb_up.available       ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]          : -1);
-    l1_rFrameUL = (char) (mb_upleft.available  ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
-    l1_rFrameUR = (char) (mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
+    l0_rFrameL  = (char) (mb_left.available    ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]       : -1);
+    l0_rFrameU  = (char) (mb_up.available      ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x]           : -1);
+    l0_rFrameUL = (char) (mb_upleft.available  ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
+    l0_rFrameUR = (char) (mb_upright.available ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
+
+    l1_rFrameL  = (char) (mb_left.available     ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]      : -1);
+    l1_rFrameU  = (char) (mb_up.available       ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]          : -1);
+    l1_rFrameUL = (char) (mb_upleft.available  ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
+    l1_rFrameUR = (char) (mb_upright.available ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
   }
   else
   {
     if (currMB->mb_field)
     {
       l0_rFrameL = (char) (mb_left.available 
-        ? img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0
-        ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] 
-        : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1);
+        ? img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0
+        ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] 
+        : dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1);
 
       l0_rFrameU = (char) (mb_up.available 
-        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0
-        ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] 
-        : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1);
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0
+        ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] 
+        : dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1);
 
        l0_rFrameUL = (char) (mb_upleft.available 
-         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0
-         ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] 
-         : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1);
+         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0
+         ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1);
 
        l0_rFrameUR = (char) (mb_upright.available 
-         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
-         ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] 
-         : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL);
+         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
+         ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL);
 
        l1_rFrameL = (char) (mb_left.available 
-         ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]  < 0 
-         ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] 
-         : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1);
+         ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1);
 
        l1_rFrameU = (char) (mb_up.available 
-         ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]  < 0 
-         ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] 
-         : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1);
+         ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1);
 
        l1_rFrameUL = (char) (mb_upleft.available 
-         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]  < 0 
-         ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] 
-         : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2 : -1);
+         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2 : -1);
 
        l1_rFrameUR = (char) (mb_upright.available 
-         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0
-         ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] 
-         : dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL);
+         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0
+         ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL);
     }
     else
     {
       l0_rFrameL = (char) (mb_left.available 
-        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]  < 0 
-        ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1);
+        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]  < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1);
 
       l0_rFrameU = (char) (mb_up.available 
-        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1);
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1);
 
       l0_rFrameUL = (char) (mb_upleft.available 
-        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 
-        : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
+        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
 
       l0_rFrameUR = (char) (mb_upright.available 
-        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
+        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
 
       l1_rFrameL = (char) (mb_left.available 
-        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1);
+        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1);
 
       l1_rFrameU = (char) (mb_up.available 
-        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1);
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1);
 
       l1_rFrameUL = (char) (mb_upleft.available 
-        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 
-        : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
+        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
 
       l1_rFrameUR = (char) (mb_upright.available 
-        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 
-        ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1
-        : dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
+        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1
+        : dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
     }
   }
 
@@ -1098,10 +1097,25 @@ void prepare_direct_params(Macroblock *currMB, StorablePicture *dec_picture, Ima
   *l1_rFrame = (char) ((*l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(*l1_rFrame,l1_rFrameUR): imax(*l1_rFrame,l1_rFrameUR));
 
   if (*l0_rFrame >=0)
-    SetMotionVectorPredictor (currMB, img, pmvl0, *l0_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
+    SetMotionVectorPredictor (img, currMB, pmvl0, *l0_rFrame, LIST_0, dec_picture->motion.ref_idx, dec_picture->motion.mv, 0, 0, 16, 16);
 
   if (*l1_rFrame >=0)
-    SetMotionVectorPredictor (currMB, img, pmvl1, *l1_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
+    SetMotionVectorPredictor (img, currMB, pmvl1, *l1_rFrame, LIST_1, dec_picture->motion.ref_idx, dec_picture->motion.mv, 0, 0, 16, 16);
+}
+
+void check_motion_vector_range(ImageParameters *img, short mv_x, short mv_y)
+{
+  if (mv_x > 8191 || mv_x < -8192)
+  {
+    fprintf(stderr,"ERROR! Horizontal motion vector %d is out of allowed range {-8192, 8191} in picture %d, macroblock %d\n", mv_x, img->number, img->current_mb_nr);
+    error("invalid stream: too big horizontal motion vector", 500);
+  }
+
+  if (mv_y > (img->max_mb_vmv_r - 1) || mv_y < (-img->max_mb_vmv_r))
+  {
+    fprintf(stderr,"ERROR! Vertical motion vector %d is out of allowed range {%d, %d} in picture %d, macroblock %d\n", mv_y, (-img->max_mb_vmv_r), (img->max_mb_vmv_r - 1), img->number, img->current_mb_nr);
+    error("invalid stream: too big vertical motion vector", 500);
+  }
 }
 
 void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *img, int pred_dir, int i, int j, int list_offset, int block_size_x, int block_size_y, int curr_mb_field)
@@ -1110,6 +1124,7 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
   static int vec1_y_cr = 0, vec2_y_cr = 0;
   static int alpha_l0, alpha_l1, wp_offset;
   static const int mv_mul = 16; // 4 * 4
+  int        max_imgpel_value = img->max_imgpel_value_comp[pl];
   
   int i4   = img->block_x + i;
   int j4   = img->block_y + j;
@@ -1121,11 +1136,13 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
   if (pred_dir != 2)
   {
     //===== Single List Prediction =====
-    short       ref_idx = dec_picture->ref_idx[pred_dir][j4][i4];
+    short       ref_idx = dec_picture->motion.ref_idx[pred_dir][j4][i4];
     short       ref_idx_wp = ref_idx;
-    short      ***mv_array = dec_picture->mv[pred_dir];
+    short      ***mv_array = dec_picture->motion.mv[pred_dir];
     StorablePicture **list = listX[list_offset + pred_dir];
 
+    check_motion_vector_range(img, mv_array[j4][i4][0], mv_array[j4][i4][1]);
+
     vec1_x = i4 * mv_mul + mv_array[j4][i4][0];
     vec1_y = (img->block_y_aff + j) * mv_mul + mv_array[j4][i4][1];
 
@@ -1142,11 +1159,11 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
       alpha_l0  = img->wp_weight[pred_dir][ref_idx_wp][0];
       wp_offset = img->wp_offset[pred_dir][ref_idx_wp][0];
 
-      weighted_mc_prediction(&img->mpr[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0, alpha_l0, wp_offset, img->luma_log2_weight_denom, img->max_imgpel_value);
+      weighted_mc_prediction(&img->mb_pred[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0, alpha_l0, wp_offset, img->luma_log2_weight_denom, max_imgpel_value);
     }
     else
     {
-      mc_prediction(&img->mpr[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0); 
+      mc_prediction(&img->mb_pred[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0); 
     }
 
     if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444) ) 
@@ -1169,11 +1186,11 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
           alpha_l0  = img->wp_weight[pred_dir][ref_idx_wp][uv + 1];
           wp_offset = img->wp_offset[pred_dir][ref_idx_wp][uv + 1];
 
-          weighted_mc_prediction(&img->mpr[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0, alpha_l0, wp_offset, img->chroma_log2_weight_denom, img->max_imgpel_value_uv);
+          weighted_mc_prediction(&img->mb_pred[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0, alpha_l0, wp_offset, img->chroma_log2_weight_denom, img->max_imgpel_value_comp[uv + 1]);
         }
         else
         {
-          mc_prediction(&img->mpr[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0);
+          mc_prediction(&img->mb_pred[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0);
         }
       }
     }
@@ -1181,14 +1198,16 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
   else
   {
     //===== BI-PREDICTION =====
-    short ***l0_mv_array = dec_picture->mv[LIST_0];
-    short ***l1_mv_array = dec_picture->mv[LIST_1];
+    short ***l0_mv_array = dec_picture->motion.mv[LIST_0];
+    short ***l1_mv_array = dec_picture->motion.mv[LIST_1];
 
-    short l0_refframe = dec_picture->ref_idx[LIST_0][j4][i4];
-    short l1_refframe = dec_picture->ref_idx[LIST_1][j4][i4];
+    short l0_refframe = dec_picture->motion.ref_idx[LIST_0][j4][i4];
+    short l1_refframe = dec_picture->motion.ref_idx[LIST_1][j4][i4];
     short l0_ref_idx  = l0_refframe;
     short l1_ref_idx  = l1_refframe;
 
+    check_motion_vector_range(img, l0_mv_array[j4][i4][0], l0_mv_array[j4][i4][1]);
+    check_motion_vector_range(img, l1_mv_array[j4][i4][0], l1_mv_array[j4][i4][1]);
     vec1_x = i4 * mv_mul + l0_mv_array[j4][i4][0];
     vec2_x = i4 * mv_mul + l1_mv_array[j4][i4][0];
 
@@ -1215,11 +1234,11 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
       alpha_l1  =   img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][0];
       wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][0] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][0] + 1) >>1);
 
-      weighted_bi_prediction(&img->mpr[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff, alpha_l0, alpha_l1, wp_offset, (img->luma_log2_weight_denom + 1), img->max_imgpel_value);
+      weighted_bi_prediction(&img->mb_pred[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff, alpha_l0, alpha_l1, wp_offset, (img->luma_log2_weight_denom + 1), max_imgpel_value);
     }
     else
     { 
-      bi_prediction(&img->mpr[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff); 
+      bi_prediction(&img->mb_pred[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff); 
     }
 
     if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444) ) 
@@ -1247,11 +1266,11 @@ void perform_mc(ColorPlane pl, StorablePicture *dec_picture, ImageParameters *im
           alpha_l1  =   img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][uv + 1];
           wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][uv + 1] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][uv + 1] + 1) >>1);
 
-          weighted_bi_prediction(&img->mpr[uv+1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr, alpha_l0, alpha_l1, wp_offset, (img->chroma_log2_weight_denom + 1), img->max_imgpel_value_uv);
+          weighted_bi_prediction(&img->mb_pred[uv+1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr, alpha_l0, alpha_l1, wp_offset, (img->chroma_log2_weight_denom + 1), img->max_imgpel_value_comp[uv + 1]);
         }
         else
         {
-          bi_prediction(&img->mpr[uv + 1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr);
+          bi_prediction(&img->mb_pred[uv + 1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr);
         }
       }
     }      
diff --git a/ldecod/src/memalloc.c b/ldecod/src/memalloc.c
index cc8c89c..8673836 100644
--- a/ldecod/src/memalloc.c
+++ b/ldecod/src/memalloc.c
@@ -872,14 +872,14 @@ int get_mem2Ddouble(double ***array2D, int rows, int columns)
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem2Ddb_offset(double ***array2D, int rows, int columns, int offset)
+int get_mem2Dodouble(double ***array2D, int rows, int columns, int offset)
 {
   int i;
 
   if((*array2D      = (double**)calloc(rows,        sizeof(double*))) == NULL)
-    no_mem_exit("get_mem2Ddb_offset: array2D");
+    no_mem_exit("get_mem2Dodouble: array2D");
   if(((*array2D)[0] = (double* )calloc(rows*columns,sizeof(double ))) == NULL)
-    no_mem_exit("get_mem2Ddb_offset: array2D");
+    no_mem_exit("get_mem2Dodouble: array2D");
 
   (*array2D)[0] += offset;
 
@@ -898,15 +898,15 @@ int get_mem2Ddb_offset(double ***array2D, int rows, int columns, int offset)
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem3Ddb_offset(double ****array3D, int rows, int columns, int pels, int offset)
+int get_mem3Dodouble(double ****array3D, int rows, int columns, int pels, int offset)
 {
   int  i,j;
 
   if(((*array3D) = (double***)calloc(rows,sizeof(double**))) == NULL)
-    no_mem_exit("get_mem3Ddb_offset: array3D");
+    no_mem_exit("get_mem3Dodouble: array3D");
 
   if(((*array3D)[0] = (double** )calloc(rows*columns,sizeof(double*))) == NULL)
-    no_mem_exit("get_mem3Ddb_offset: array3D");
+    no_mem_exit("get_mem3Dodouble: array3D");
 
   (*array3D) [0] += offset;
 
@@ -916,7 +916,7 @@ int get_mem3Ddb_offset(double ****array3D, int rows, int columns, int pels, int
   for (i = 0; i < rows; i++)
     for (j = -offset; j < columns - offset; j++)
       if(((*array3D)[i][j] = (double* )calloc(pels,sizeof(double))) == NULL)
-        no_mem_exit("get_mem3Ddb_offset: array3D");
+        no_mem_exit("get_mem3Dodouble: array3D");
 
   return rows*columns*pels*sizeof(double);
 }
@@ -963,15 +963,15 @@ int get_offset_mem2Dshort(short ***array2D, int rows, int columns, int offset_y,
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int offset)
+int get_mem3Doint(int ****array3D, int rows, int columns, int pels, int offset)
 {
   int  i,j;
 
   if(((*array3D) = (int***)calloc(rows,sizeof(int**))) == NULL)
-    no_mem_exit("get_mem3Dint_offset: array3D");
+    no_mem_exit("get_mem3Doint: array3D");
 
   if(((*array3D)[0] = (int** )calloc(rows*columns,sizeof(int*))) == NULL)
-    no_mem_exit("get_mem3Dint_offset: array3D");
+    no_mem_exit("get_mem3Doint: array3D");
 
   (*array3D) [0] += offset;
 
@@ -981,7 +981,7 @@ int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int of
   for (i = 0; i < rows; i++)
     for (j = -offset; j < columns - offset; j++)
       if(((*array3D)[i][j] = (int* )calloc(pels,sizeof(int))) == NULL)
-        no_mem_exit("get_mem3Dint_offset: array3D");
+        no_mem_exit("get_mem3Doint: array3D");
 
   return rows*columns*pels*sizeof(int);
 }
@@ -996,7 +996,7 @@ int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int of
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem2Dint_offset(int ***array2D, int rows, int columns, int offset)
+int get_mem2Doint(int ***array2D, int rows, int columns, int offset)
 {
   int i;
 
@@ -1076,20 +1076,20 @@ void free_mem2Ddouble(double **array2D)
 *    which was allocated with get_mem2Ddouble()
 ************************************************************************
 */
-void free_mem2Ddb_offset(double **array2D, int offset)
+void free_mem2Dodouble(double **array2D, int offset)
 {
   if (array2D)
   {
     array2D[0] -= offset;
     if (array2D[0])
       free (array2D[0]);
-    else error ("free_mem2Ddb_offset: trying to free unused memory",100);
+    else error ("free_mem2Dodouble: trying to free unused memory",100);
 
     free (array2D);
 
   } else
   {
-    error ("free_mem2Ddb_offset: trying to free unused memory",100);
+    error ("free_mem2Dodouble: trying to free unused memory",100);
   }
 }
 
@@ -1099,7 +1099,7 @@ void free_mem2Ddb_offset(double **array2D, int offset)
  *    free 3D memory array with offset
  ************************************************************************
  */
-void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
+void free_mem3Dodouble(double ***array3D, int rows, int columns, int offset)
 {
   int i, j;
 
@@ -1112,19 +1112,19 @@ void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
         if (array3D[i][j])
           free(array3D[i][j]);
         else
-          error ("free_mem3Ddb_offset: trying to free unused memory",100);
+          error ("free_mem3Dodouble: trying to free unused memory",100);
       }
     }
     array3D[0] -= offset;
     if (array3D[0])
       free(array3D[0]);
     else
-      error ("free_mem3Ddb_offset: trying to free unused memory",100);
+      error ("free_mem3Dodouble: trying to free unused memory",100);
     free (array3D);
   }
   else
   {
-    error ("free_mem3Ddb_offset: trying to free unused memory",100);
+    error ("free_mem3Dodouble: trying to free unused memory",100);
   }
 }
 
@@ -1134,7 +1134,7 @@ void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
  *    free 3D memory array with offset
  ************************************************************************
  */
-void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
+void free_mem3Doint(int ***array3D, int rows, int columns, int offset)
 {
   int i, j;
 
@@ -1147,19 +1147,19 @@ void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
         if (array3D[i][j])
           free(array3D[i][j]);
         else
-          error ("free_mem3Dint_offset: trying to free unused memory",100);
+          error ("free_mem3Doint: trying to free unused memory",100);
       }
     }
     array3D[0] -= offset;
     if (array3D[0])
       free(array3D[0]);
     else
-      error ("free_mem3Dint_offset: trying to free unused memory",100);
+      error ("free_mem3Doint: trying to free unused memory",100);
     free (array3D);
   }
   else
   {
-    error ("free_mem3Dint_offset: trying to free unused memory",100);
+    error ("free_mem3Doint: trying to free unused memory",100);
   }
 }
 
@@ -1171,7 +1171,7 @@ void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
 *    which was allocated with get_mem2Ddouble()
 ************************************************************************
 */
-void free_mem2Dint_offset(int **array2D, int offset)
+void free_mem2Doint(int **array2D, int offset)
 {
   if (array2D)
   {
@@ -1179,14 +1179,14 @@ void free_mem2Dint_offset(int **array2D, int offset)
     if (array2D[0])
       free (array2D[0]);
     else 
-      error ("free_mem2Dint_offset: trying to free unused memory",100);
+      error ("free_mem2Doint: trying to free unused memory",100);
 
     free (array2D);
 
   } 
   else
   {
-    error ("free_mem2Dint_offset: trying to free unused memory",100);
+    error ("free_mem2Doint: trying to free unused memory",100);
   }
 }
 
diff --git a/ldecod/src/nalu.c b/ldecod/src/nalu.c
index 5951967..09bbbe0 100644
--- a/ldecod/src/nalu.c
+++ b/ldecod/src/nalu.c
@@ -14,7 +14,8 @@
 
 #include "global.h"
 #include "nalu.h"
-
+#include "annexb.h"
+#include "rtp.h"
 
 /*!
  *************************************************************************************
@@ -38,3 +39,47 @@ int NALUtoRBSP (NALU_t *nalu)
   return nalu->len ;
 }
 
+/*!
+************************************************************************
+* \brief
+*    Read the next NAL unit (with error handling)
+************************************************************************
+*/
+int read_next_nalu(FILE *bitstream, NALU_t *nalu)
+{
+  int ret;
+
+  if (params->FileFormat == PAR_OF_ANNEXB)
+    ret = GetAnnexbNALU (bitstream, nalu);
+  else
+    ret = GetRTPNALU (bitstream, nalu);
+
+  if (ret < 0)
+  {
+    snprintf (errortext, ET_SIZE, "Error while getting the NALU in file format %s, exit\n", params->FileFormat==PAR_OF_ANNEXB?"Annex B":"RTP");
+    error (errortext, 601);
+  }
+  if (ret == 0)
+  {
+    FreeNALU(nalu);
+    return 0;
+  }
+
+  //In some cases, zero_byte shall be present. If current NALU is a VCL NALU, we can't tell
+  //whether it is the first VCL NALU at this point, so only non-VCL NAL unit is checked here.
+  CheckZeroByteNonVCL(nalu);
+
+  ret = NALUtoRBSP(nalu);
+
+  if (ret < 0)
+    error ("Invalid startcode emulation prevention found.", 602);
+
+
+  // Got a NALU
+  if (nalu->forbidden_bit)
+  {
+    error ("Found NALU with forbidden_bit set, bit error?", 603);
+  }
+
+  return nalu->len;
+}
diff --git a/ldecod/src/output.c b/ldecod/src/output.c
index 313aafe..3d870d7 100644
--- a/ldecod/src/output.c
+++ b/ldecod/src/output.c
@@ -28,11 +28,11 @@ int recovery_flag = 0;
 
 extern int non_conforming_stream;
 
-void write_out_picture(StorablePicture *p, int p_out);
-void (*img2buf)     (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
-void img2buf_byte   (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
-void img2buf_normal (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
-void img2buf_endian (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
+static void write_out_picture(StorablePicture *p, int p_out);
+static void (*img2buf)     (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
+static void img2buf_byte   (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
+static void img2buf_normal (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
+static void img2buf_endian (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom);
 
 /*!
  ************************************************************************
@@ -64,7 +64,7 @@ int testEndian(void)
  *
  ************************************************************************
  */
-void initOutput(int symbol_size_in_bytes)
+static void initOutput(int symbol_size_in_bytes)
 {
   if (( sizeof(char) == sizeof (imgpel)) && ( sizeof(char) == symbol_size_in_bytes))
   {
@@ -103,7 +103,7 @@ void initOutput(int symbol_size_in_bytes)
  *    pixels to crop from bottom
  ************************************************************************
  */
-void img2buf_normal (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
+static void img2buf_normal (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
 {
   int i,j;
 
@@ -171,7 +171,7 @@ void img2buf_normal (imgpel** imgX, unsigned char* buf, int size_x, int size_y,
  *    pixels to crop from bottom
  ************************************************************************
  */
-void img2buf_byte (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
+static void img2buf_byte (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
 {
   int i;
 
@@ -211,7 +211,7 @@ void img2buf_byte (imgpel** imgX, unsigned char* buf, int size_x, int size_y, in
  *    pixels to crop from bottom
  ************************************************************************
  */
-void img2buf_endian (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
+static void img2buf_endian (imgpel** imgX, unsigned char* buf, int size_x, int size_y, int symbol_size_in_bytes, int crop_left, int crop_right, int crop_top, int crop_bottom)
 {
   int i,j;
   static unsigned char  ui8;
@@ -445,7 +445,7 @@ void write_picture(StorablePicture *p, int p_out, int real_structure)
 *    Output file
 ************************************************************************
 */
-void write_out_picture(StorablePicture *p, int p_out)
+static void write_out_picture(StorablePicture *p, int p_out)
 {
   static int SubWidthC  [4]= { 1, 2, 2, 1};
   static int SubHeightC [4]= { 1, 2, 1, 1};
diff --git a/ldecod/src/parset.c b/ldecod/src/parset.c
index 17cf7fd..363fb8d 100644
--- a/ldecod/src/parset.c
+++ b/ldecod/src/parset.c
@@ -188,7 +188,7 @@ int InterpretSPS (DataPartition *p, seq_parameter_set_rbsp_t *sps)
     sps->mb_adaptive_frame_field_flag        = u_1  ("SPS: mb_adaptive_frame_field_flag"           , s);
   }
   sps->direct_8x8_inference_flag             = u_1  ("SPS: direct_8x8_inference_flag"              , s);
-  sps->frame_cropping_flag                   = u_1  ("SPS: frame_cropping_flag"                , s);
+  sps->frame_cropping_flag                   = u_1  ("SPS: frame_cropping_flag"                    , s);
 
   if (sps->frame_cropping_flag)
   {
@@ -197,7 +197,7 @@ int InterpretSPS (DataPartition *p, seq_parameter_set_rbsp_t *sps)
     sps->frame_cropping_rect_top_offset       = ue_v ("SPS: frame_cropping_rect_top_offset"            , s);
     sps->frame_cropping_rect_bottom_offset    = ue_v ("SPS: frame_cropping_rect_bottom_offset"         , s);
   }
-  sps->vui_parameters_present_flag           = (Boolean) u_1  ("SPS: vui_parameters_present_flag"            , s);
+  sps->vui_parameters_present_flag           = (Boolean) u_1  ("SPS: vui_parameters_present_flag"      , s);
 
   InitVUI(sps);
   ReadVUI(p, sps);
@@ -581,6 +581,24 @@ void activate_sps (seq_parameter_set_rbsp_t *sps)
     img->width_cr        = 0;
     img->height_cr       = 0;
 
+    // maximum vertical motion vector range in luma quarter pixel units
+    if (active_sps->level_idc <= 10)
+    {
+      img->max_vmv_r = 64 * 4;
+    }
+    else if (active_sps->level_idc <= 20)
+    {
+      img->max_vmv_r = 128 * 4;
+    }
+    else if (active_sps->level_idc <= 30)
+    {
+      img->max_vmv_r = 256 * 4;
+    }
+    else
+    {
+      img->max_vmv_r = 512 * 4; // 512 pixels in quarter pixels
+    }
+
     // Fidelity Range Extensions stuff (part 1)
     img->bitdepth_luma       = sps->bit_depth_luma_minus8 + 8;
     img->bitdepth_scale[0]   = 1 << sps->bit_depth_luma_minus8;
diff --git a/ldecod/src/quant.c b/ldecod/src/quant.c
new file mode 100644
index 0000000..7dcb6d7
--- /dev/null
+++ b/ldecod/src/quant.c
@@ -0,0 +1,459 @@
+
+/*!
+ ***********************************************************************
+ *  \file
+ *      quant.c
+ *
+ *  \brief
+ *      Quantization functions
+ *
+ *  \author
+ *      Main contributors (see contributors.h for copyright, address and affiliation details)
+ *
+ ***********************************************************************
+ */
+
+#include "contributors.h"
+
+#include "global.h"
+#include "memalloc.h"
+#include "block.h"
+#include "image.h"
+#include "mb_access.h"
+#include "transform.h"
+#include "quant.h"
+
+const int dequant_coef8[6][8][8] =
+{
+  {
+    {20,  19, 25, 19, 20, 19, 25, 19},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {25,  24, 32, 24, 25, 24, 32, 24},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {20,  19, 25, 19, 20, 19, 25, 19},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {25,  24, 32, 24, 25, 24, 32, 24},
+    {19,  18, 24, 18, 19, 18, 24, 18}
+  },
+  {
+    {22,  21, 28, 21, 22, 21, 28, 21},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {22,  21, 28, 21, 22, 21, 28, 21},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {21,  19, 26, 19, 21, 19, 26, 19}
+  },
+  {
+    {26,  24, 33, 24, 26, 24, 33, 24},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {33,  31, 42, 31, 33, 31, 42, 31},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {26,  24, 33, 24, 26, 24, 33, 24},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {33,  31, 42, 31, 33, 31, 42, 31},
+    {24,  23, 31, 23, 24, 23, 31, 23}
+  },
+  {
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {35,  33, 45, 33, 35, 33, 45, 33},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {35,  33, 45, 33, 35, 33, 45, 33},
+    {26,  25, 33, 25, 26, 25, 33, 25}
+  },
+  {
+    {32,  30, 40, 30, 32, 30, 40, 30},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {40,  38, 51, 38, 40, 38, 51, 38},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {32,  30, 40, 30, 32, 30, 40, 30},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {40,  38, 51, 38, 40, 38, 51, 38},
+    {30,  28, 38, 28, 30, 28, 38, 28}
+  },
+  {
+    {36,  34, 46, 34, 36, 34, 46, 34},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {46,  43, 58, 43, 46, 43, 58, 43},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {36,  34, 46, 34, 36, 34, 46, 34},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {46,  43, 58, 43, 46, 43, 58, 43},
+    {34,  32, 43, 32, 34, 32, 43, 32}
+  }
+};
+
+//! Dequantization coefficients
+const int dequant_coef[6][4][4] = {
+  {
+    { 10, 13, 10, 13},
+    { 13, 16, 13, 16},
+    { 10, 13, 10, 13},
+    { 13, 16, 13, 16}},
+  {
+    { 11, 14, 11, 14},
+    { 14, 18, 14, 18},
+    { 11, 14, 11, 14},
+    { 14, 18, 14, 18}},
+  {
+    { 13, 16, 13, 16},
+    { 16, 20, 16, 20},
+    { 13, 16, 13, 16},
+    { 16, 20, 16, 20}},
+  {
+    { 14, 18, 14, 18},
+    { 18, 23, 18, 23},
+    { 14, 18, 14, 18},
+    { 18, 23, 18, 23}},
+  {
+    { 16, 20, 16, 20},
+    { 20, 25, 20, 25},
+    { 16, 20, 16, 20},
+    { 20, 25, 20, 25}},
+  {
+    { 18, 23, 18, 23},
+    { 23, 29, 23, 29},
+    { 18, 23, 18, 23},
+    { 23, 29, 23, 29}}
+};
+
+const int quant_coef[6][4][4] = {
+  {
+    { 13107,  8066, 13107,  8066},
+    {  8066,  5243,  8066,  5243},
+    { 13107,  8066, 13107,  8066},
+    {  8066,  5243,  8066,  5243}},
+  {
+    { 11916,  7490, 11916,  7490},
+    {  7490,  4660,  7490,  4660},
+    { 11916,  7490, 11916,  7490},
+    {  7490,  4660,  7490,  4660}},
+  {
+    { 10082,  6554, 10082,  6554},
+    {  6554,  4194,  6554,  4194},
+    { 10082,  6554, 10082,  6554},
+    {  6554,  4194,  6554,  4194}},
+  {
+    {  9362,  5825,  9362,  5825},
+    {  5825,  3647,  5825,  3647},
+    {  9362,  5825,  9362,  5825},
+    {  5825,  3647,  5825,  3647}},
+  {
+    {  8192,  5243,  8192,  5243},
+    {  5243,  3355,  5243,  3355},
+    {  8192,  5243,  8192,  5243},
+    {  5243,  3355,  5243,  3355}},
+  {
+    {  7282,  4559,  7282,  4559},
+    {  4559,  2893,  4559,  2893},
+    {  7282,  4559,  7282,  4559},
+    {  4559,  2893,  4559,  2893}}
+};
+
+const int A[4][4] = {
+  { 16, 20, 16, 20},
+  { 20, 25, 20, 25},
+  { 16, 20, 16, 20},
+  { 20, 25, 20, 25}
+};
+
+int quant_intra_default[16] = {
+   6,13,20,28,
+  13,20,28,32,
+  20,28,32,37,
+  28,32,37,42
+};
+
+int quant_inter_default[16] = {
+  10,14,20,24,
+  14,20,24,27,
+  20,24,27,30,
+  24,27,30,34
+};
+
+int quant8_intra_default[64] = {
+ 6,10,13,16,18,23,25,27,
+10,11,16,18,23,25,27,29,
+13,16,18,23,25,27,29,31,
+16,18,23,25,27,29,31,33,
+18,23,25,27,29,31,33,36,
+23,25,27,29,31,33,36,38,
+25,27,29,31,33,36,38,40,
+27,29,31,33,36,38,40,42
+};
+
+int quant8_inter_default[64] = {
+ 9,13,15,17,19,21,22,24,
+13,13,17,19,21,22,24,25,
+15,17,19,21,22,24,25,27,
+17,19,21,22,24,25,27,28,
+19,21,22,24,25,27,28,30,
+21,22,24,25,27,28,30,32,
+22,24,25,27,28,30,32,33,
+24,25,27,28,30,32,33,35
+};
+
+int quant_org[16] = { //to be use if no q matrix is chosen
+16,16,16,16,
+16,16,16,16,
+16,16,16,16,
+16,16,16,16
+};
+
+int quant8_org[64] = { //to be use if no q matrix is chosen
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16
+};
+
+int *qp_per_matrix;
+int *qp_rem_matrix;
+
+int  InvLevelScale4x4_Intra[3][6][4][4];
+int  InvLevelScale4x4_Inter[3][6][4][4];
+int  InvLevelScale8x8_Intra[3][6][8][8];
+int  InvLevelScale8x8_Inter[3][6][8][8];
+
+int  *qmatrix[12];
+
+/*!
+ ***********************************************************************
+ * \brief
+ *    Initiate quantization process arrays
+ ***********************************************************************
+ */
+void init_qp_process(ImageParameters *img)
+{
+  int bitdepth_qp_scale = imax(img->bitdepth_luma_qp_scale,img->bitdepth_chroma_qp_scale);
+  int i;
+
+  // We should allocate memory outside of this process since maybe we will have a change of SPS 
+  // and we may need to recreate these. Currently should only support same bitdepth
+  if (qp_per_matrix == NULL)
+    if ((qp_per_matrix = (int*)malloc((MAX_QP + 1 +  bitdepth_qp_scale)*sizeof(int))) == NULL)
+      no_mem_exit("init_global_buffers: qp_per_matrix");
+  if (qp_rem_matrix == NULL)
+    if ((qp_rem_matrix = (int*)malloc((MAX_QP + 1 +  bitdepth_qp_scale)*sizeof(int))) == NULL)
+      no_mem_exit("init_global_buffers: qp_per_matrix");
+
+  for (i = 0; i < MAX_QP + bitdepth_qp_scale + 1; i++)
+  {
+    qp_per_matrix[i] = i / 6;
+    qp_rem_matrix[i] = i % 6;
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    For mapping the q-matrix to the active id and calculate quantisation values
+ *
+ * \param pps
+ *    Picture parameter set
+ * \param sps
+ *    Sequence parameter set
+ *
+ ************************************************************************
+ */
+void AssignQuantParam(pic_parameter_set_rbsp_t* pps, seq_parameter_set_rbsp_t* sps)
+{
+  int i;
+  int n_ScalingList;
+
+  if(!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag)
+  {
+    for(i=0; i<12; i++)
+      qmatrix[i] = (i<6) ? quant_org:quant8_org;
+  }
+  else
+  {
+    n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;
+    if(sps->seq_scaling_matrix_present_flag) // check sps first
+    {
+      for(i=0; i<n_ScalingList; i++)
+      {
+        if(i<6)
+        {
+          if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A
+          {
+            if(i==0)
+              qmatrix[i] = quant_intra_default;
+            else if(i==3)
+              qmatrix[i] = quant_inter_default;
+            else
+              qmatrix[i] = qmatrix[i-1];
+          }
+          else
+          {
+            if(sps->UseDefaultScalingMatrix4x4Flag[i])
+              qmatrix[i] = (i<3) ? quant_intra_default : quant_inter_default;
+            else
+              qmatrix[i] = sps->ScalingList4x4[i];
+          }
+        }
+        else
+        {
+          if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A
+          {
+            if(i==6)
+              qmatrix[i] = quant8_intra_default;
+            else if(i==7)
+              qmatrix[i] = quant8_inter_default;
+            else
+              qmatrix[i] = qmatrix[i-2];
+          }
+          else
+          {
+            if(sps->UseDefaultScalingMatrix8x8Flag[i-6])
+              qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;
+            else
+              qmatrix[i] = sps->ScalingList8x8[i-6];
+          }
+        }
+      }
+    }
+
+    if(pps->pic_scaling_matrix_present_flag) // then check pps
+    {
+      for(i=0; i<n_ScalingList; i++)
+      {
+        if(i<6)
+        {
+          if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B
+          {
+            if (i==0)
+            {
+              if(!sps->seq_scaling_matrix_present_flag)
+                qmatrix[i] = quant_intra_default;
+            }
+            else if (i==3)
+            {
+              if(!sps->seq_scaling_matrix_present_flag)
+                qmatrix[i] = quant_inter_default;
+            }
+            else
+              qmatrix[i] = qmatrix[i-1];
+          }
+          else
+          {
+            if(pps->UseDefaultScalingMatrix4x4Flag[i])
+              qmatrix[i] = (i<3) ? quant_intra_default:quant_inter_default;
+            else
+              qmatrix[i] = pps->ScalingList4x4[i];
+          }
+        }
+        else
+        {
+          if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B
+          {
+            if (i==6)
+            {
+              if(!sps->seq_scaling_matrix_present_flag)
+                qmatrix[i] = quant8_intra_default;
+            }
+            else if(i==7)
+            {
+              if(!sps->seq_scaling_matrix_present_flag)
+                qmatrix[i] = quant8_inter_default;
+            }
+            else  
+              qmatrix[i] = qmatrix[i-2];
+          }
+          else
+          {
+            if(pps->UseDefaultScalingMatrix8x8Flag[i-6])
+              qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;
+            else
+              qmatrix[i] = pps->ScalingList8x8[i-6];
+          }
+        }
+      }
+    }
+  }
+
+  CalculateQuantParam();
+  if(pps->transform_8x8_mode_flag)
+    CalculateQuant8Param();
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    For calculating the quantisation values at frame level
+ *
+ ************************************************************************
+ */
+void CalculateQuantParam()
+{
+  int i, j, k, temp;
+
+  for(k=0; k<6; k++)
+  {
+    for(i=0; i<4; i++)
+    {
+      for(j=0; j<4; j++)
+      {
+        temp = (i<<2)+j;
+        InvLevelScale4x4_Intra[0][k][i][j] = dequant_coef[k][i][j] * qmatrix[0][temp];
+        InvLevelScale4x4_Intra[1][k][i][j] = dequant_coef[k][i][j] * qmatrix[1][temp];
+        InvLevelScale4x4_Intra[2][k][i][j] = dequant_coef[k][i][j] * qmatrix[2][temp];
+
+        InvLevelScale4x4_Inter[0][k][i][j] = dequant_coef[k][i][j] * qmatrix[3][temp];
+        InvLevelScale4x4_Inter[1][k][i][j] = dequant_coef[k][i][j] * qmatrix[4][temp];
+        InvLevelScale4x4_Inter[2][k][i][j] = dequant_coef[k][i][j] * qmatrix[5][temp];
+      }
+    }
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Calculate the quantisation and inverse quantisation parameters
+ *
+ ************************************************************************
+ */
+void CalculateQuant8Param()
+{
+  int i, j, k, temp;
+
+  for(k=0; k<6; k++)
+  {
+    for(i=0; i<8; i++)
+    {
+      for(j=0; j<8; j++)
+      {
+        temp = (i<<3)+j;
+        InvLevelScale8x8_Intra[0][k][i][j] = dequant_coef8[k][i][j] * qmatrix[6][temp];
+        InvLevelScale8x8_Inter[0][k][i][j] = dequant_coef8[k][i][j] * qmatrix[7][temp];
+      }
+    }
+  }
+
+  if( active_sps->chroma_format_idc == 3 )  // 4:4:4
+  {
+    for(k=0; k<6; k++)
+    {
+      for(i=0; i<8; i++)
+      {
+        for(j=0; j<8; j++)
+        {
+          temp = (i<<3)+j;
+          InvLevelScale8x8_Intra[1][k][i][j] = dequant_coef8[k][i][j] * qmatrix[8][temp];
+          InvLevelScale8x8_Inter[1][k][i][j] = dequant_coef8[k][i][j] * qmatrix[9][temp];
+          InvLevelScale8x8_Intra[2][k][i][j] = dequant_coef8[k][i][j] * qmatrix[10][temp];
+          InvLevelScale8x8_Inter[2][k][i][j] = dequant_coef8[k][i][j] * qmatrix[11][temp];
+        }
+      }
+    }
+  }
+}
diff --git a/ldecod/src/rtp.c b/ldecod/src/rtp.c
index 0f70178..d6791dd 100644
--- a/ldecod/src/rtp.c
+++ b/ldecod/src/rtp.c
@@ -102,7 +102,7 @@
 
 FILE *bits;
 
-int RTPReadPacket (RTPpacket_t *p, FILE *bits);
+int RTPReadPacket (RTPpacket_t *p, FILE *bitstream);
 
 /*!
  ************************************************************************
@@ -149,7 +149,7 @@ void CloseRTPFile(void)
  ************************************************************************
  */
 
-int GetRTPNALU (NALU_t *nalu)
+int GetRTPNALU (FILE *bitstream, NALU_t *nalu)
 {
   static unsigned short first_call = 1;  //!< triggers sequence number initialization on first call
   static unsigned short old_seq = 0;     //!< store the last RTP sequence number for loss detection
@@ -164,7 +164,7 @@ int GetRTPNALU (NALU_t *nalu)
   if ((p->payload=malloc (MAXRTPPACKETSIZE))== NULL)
     no_mem_exit ("GetRTPNALU-3");
 
-  ret = RTPReadPacket (p, bits);
+  ret = RTPReadPacket (p, bitstream);
   nalu->forbidden_bit = 1;
   nalu->len = 0;
 
@@ -344,7 +344,7 @@ void DumpRTPHeader (RTPpacket_t *p)
  *    Stephan Wenger, stewe@cs.tu-berlin.de
  *****************************************************************************/
 
-int RTPReadPacket (RTPpacket_t *p, FILE *bits)
+int RTPReadPacket (RTPpacket_t *p, FILE *bitstream)
 {
   int Filepos, intime;
 
@@ -352,22 +352,22 @@ int RTPReadPacket (RTPpacket_t *p, FILE *bits)
   assert (p->packet != NULL);
   assert (p->payload != NULL);
 
-  Filepos = ftell (bits);
-  if (4 != fread (&p->packlen,1, 4, bits))
+  Filepos = ftell (bitstream);
+  if (4 != fread (&p->packlen,1, 4, bitstream))
   {
     return 0;
   }
 
-  if (4 != fread (&intime, 1, 4, bits))
+  if (4 != fread (&intime, 1, 4, bitstream))
   {
-    fseek (bits, Filepos, SEEK_SET);
+    fseek (bitstream, Filepos, SEEK_SET);
     printf ("RTPReadPacket: File corruption, could not read Timestamp, exit\n");
     exit (-1);
   }
 
   assert (p->packlen < MAXRTPPACKETSIZE);
 
-  if (p->packlen != fread (p->packet, 1, p->packlen, bits))
+  if (p->packlen != fread (p->packet, 1, p->packlen, bitstream))
   {
     printf ("RTPReadPacket: File corruption, could not read %d bytes\n", (int) p->packlen);
     exit (-1);    // EOF inidication
diff --git a/ldecod/src/sei.c b/ldecod/src/sei.c
index 571b3c0..6492f98 100644
--- a/ldecod/src/sei.c
+++ b/ldecod/src/sei.c
@@ -407,7 +407,7 @@ void interpret_spare_pic( byte* payload, int size, ImageParameters *img )
       for (i=0; i < img->height/16; i++)
         for (j=0; j < img->width/16; j++)
         {
-          tmp=map[kk][i][j]==0? img->max_imgpel_value : 0;
+          tmp=map[kk][i][j]==0? img->max_imgpel_value_comp[0] : 0;
           for (i0=0; i0<16; i0++)
             for (j0=0; j0<16; j0++)
               Y[i*16+i0][j*16+j0]=tmp;
diff --git a/ldecod/src/transform8x8.c b/ldecod/src/transform8x8.c
index 4890f38..5e2b73f 100644
--- a/ldecod/src/transform8x8.c
+++ b/ldecod/src/transform8x8.c
@@ -23,140 +23,9 @@
 #include "elements.h"
 #include "transform8x8.h"
 #include "transform.h"
+#include "quant.h"
 
-#define Q_BITS_8        16
-#define DQ_BITS_8       6 
 
-const int quant_coef8[6][8][8] =
-{
-  {
-    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428}
-  },
-  {
-    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826}
-  },
-  {
-    {10082, 9675, 12710,  9675, 10082,  9675, 12710,  9675},
-    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
-    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
-    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
-    {10082, 9675, 12710,  9675, 10082,  9675, 12710,  9675},
-    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
-    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
-    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943}
-  },
-  {
-    {9362,  8931, 11984,  8931, 9362, 8931, 11984,  8931},
-    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
-    {11984, 11259,  14913,  11259,  11984,  11259,  14913,  11259},
-    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
-    {9362,  8931, 11984,  8931, 9362, 8931, 11984,  8931},
-    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
-    {11984, 11259,  14913,  11259,  11984,  11259,  14913,  11259},
-    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228}
-  },
-  {
-    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346}
-  },
-  {
-    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428}
-  }
-};
-
-
-
-const int dequant_coef8[6][8][8] =
-{
-  {
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18}
-  },
-  {
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19}
-  },
-  {
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23}
-  },
-  {
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25}
-  },
-  {
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28}
-  },
-  {
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32}
-  }
-
-};
 
 // function declarations
 void   LowPassForIntra8x8Pred(imgpel *PredPel, int block_up_left, int block_up, int block_left);
@@ -218,10 +87,10 @@ void   LowPassForIntra8x8Pred(imgpel *PredPel, int block_up_left, int block_up,
  *
  ************************************************************************
  */
-int intrapred8x8( ColorPlane pl,        //!< Current Colorplane
-                  ImageParameters *img,  //!< image parameters
-                  Macroblock *currMB,   //!< Current Macroblock
-                  int b8)
+int intrapred8x8(ImageParameters *img,  //!< image parameters
+                 Macroblock *currMB,   //!< Current Macroblock 
+                 ColorPlane pl,        //!< Current Colorplane                 
+                 int b8)
 
 {
   int i,j;
@@ -246,7 +115,7 @@ int intrapred8x8( ColorPlane pl,        //!< Current Colorplane
   int ipos0 = ioff    , ipos1 = ioff + 1, ipos2 = ioff + 2, ipos3 = ioff + 3;
   int ipos4 = ioff + 4, ipos5 = ioff + 5, ipos6 = ioff + 6, ipos7 = ioff + 7;
   int jpos, ipos;
-  imgpel *pred_pels, (*mpr)[16] = img->mpr[pl];
+  imgpel *pred_pels, (*mpr)[16] = img->mb_pred[pl];
   int *mb_size = img->mb_size[IS_LUMA];
 
   byte predmode = img->ipredmode[img_block_y][img_block_x];
@@ -908,17 +777,18 @@ void LowPassForIntra8x8Pred(imgpel *PredPel, int block_up_left, int block_up, in
  *    Inverse 8x8 transformation
  ***********************************************************************
  */ 
-void itrans8x8(ColorPlane pl,
-               ImageParameters *img, //!< image parameters
-              int ioff,            //!< index to 4x4 block
-              int joff)            //!<
+void itrans8x8(ImageParameters *img, //!< image parameters
+               Macroblock *currMB,
+               ColorPlane pl,               
+               int ioff,            //!< index to 4x4 block
+               int joff)            //!<
 {
   int i,j;
-  Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
+  Boolean lossless_qpprime = (Boolean) (currMB->qp_scaled[pl] == 0 && img->lossless_qpprime_flag==1);
 
-  imgpel (*mpr)[16] = img->mpr[pl];
-  int    (*m7)[16] = img->m7[pl];
-  int     max_imgpel_value = pl ? img->max_imgpel_value_uv : img->max_imgpel_value;
+  imgpel (*mpr)[16] = img->mb_pred[pl];
+  int    (*m7)[16]  = img->mb_rres[pl];
+  int     max_imgpel_value = img->max_imgpel_value_comp[pl];
 
   if(lossless_qpprime)
   {
diff --git a/ldecod/src/vlc.c b/ldecod/src/vlc.c
index 9217fca..31298f9 100644
--- a/ldecod/src/vlc.c
+++ b/ldecod/src/vlc.c
@@ -26,13 +26,31 @@
 #define SYMTRACESTRING(s) // do nothing
 #endif
 
-extern void tracebits(const char *trace_str,  int len,  int info,int value1);
+void tracebits(const char *trace_str,  int len,  int info,int value1);
+
 
 
 int UsedBits;      // for internal statistics, is adjusted by se_v, ue_v, u_1
 
 // Note that all NA values are filled with 0
 
+//! gives CBP value from codeword number, both for intra and inter
+static const unsigned char NCBP[2][48][2]=
+{
+  {  // 0      1        2       3       4       5       6       7       8       9      10      11
+    {15, 0},{ 0, 1},{ 7, 2},{11, 4},{13, 8},{14, 3},{ 3, 5},{ 5,10},{10,12},{12,15},{ 1, 7},{ 2,11},
+    { 4,13},{ 8,14},{ 6, 6},{ 9, 9},{ 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}
+  },
+  {
+    {47, 0},{31,16},{15, 1},{ 0, 2},{23, 4},{27, 8},{29,32},{30, 3},{ 7, 5},{11,10},{13,12},{14,15},
+    {39,47},{43, 7},{45,11},{46,13},{16,14},{ 3, 6},{ 5, 9},{10,31},{12,35},{19,37},{21,42},{26,44},
+    {28,33},{35,34},{37,36},{42,40},{44,39},{ 1,43},{ 2,45},{ 4,46},{ 8,17},{17,18},{18,20},{20,24},
+    {24,19},{ 6,21},{ 9,26},{22,28},{25,23},{32,27},{33,29},{34,30},{36,22},{40,25},{38,38},{41,41}
+  }
+};
+
 //! for the linfo_levrun_inter routine
 const byte NTAB1[4][8][2] =
 {
@@ -275,7 +293,6 @@ void linfo_se(int len,  int info, int *value1, int *dummy)
  */
 void linfo_cbp_intra(int len,int info,int *cbp, int *dummy)
 {
-  extern const byte NCBP[2][48][2];
   int cbp_idx;
 
   linfo_ue(len, info, &cbp_idx, dummy);
@@ -296,7 +313,6 @@ void linfo_cbp_intra(int len,int info,int *cbp, int *dummy)
  */
 void linfo_cbp_inter(int len,int info,int *cbp, int *dummy)
 {
-  extern const byte NCBP[2][48][2];
   int cbp_idx;
 
   linfo_ue(len, info, &cbp_idx, dummy);
@@ -530,10 +546,10 @@ int more_rbsp_data (byte buffer[],int totbitoffset,int bytecount)
  *    Check if there are symbols for the next MB
  ************************************************************************
  */
-int uvlc_startcode_follows(ImageParameters *img, int dummy)
+int uvlc_startcode_follows(Slice *currSlice, int dummy)
 {
-  int dp_Nr = assignSE2partition[img->currentSlice->dp_mode][SE_MBTYPE];
-  DataPartition *dP = &(img->currentSlice->partArr[dp_Nr]);
+  int dp_Nr = assignSE2partition[currSlice->dp_mode][SE_MBTYPE];
+  DataPartition *dP = &(currSlice->partArr[dp_Nr]);
   Bitstream   *currStream = dP->bitstream;
   byte *buf  = currStream->streamBuffer;
 
diff --git a/ldecod_vc7.vcproj b/ldecod_vc7.vcproj
index cac3788..dd35f02 100644
--- a/ldecod_vc7.vcproj
+++ b/ldecod_vc7.vcproj
@@ -233,6 +233,9 @@
 			<File
 				RelativePath=".\ldecod\src\parsetcommon.c">
 			</File>
+			<File
+				RelativePath=".\ldecod\src\quant.c">
+			</File>
 			<File
 				RelativePath=".\ldecod\src\rtp.c">
 			</File>
@@ -294,6 +297,9 @@
 			<File
 				RelativePath=".\ldecod\inc\fmo.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\frame.h">
+			</File>
 			<File
 				RelativePath=".\ldecod\inc\global.h">
 			</File>
@@ -342,6 +348,9 @@
 			<File
 				RelativePath=".\ldecod\inc\parsetcommon.h">
 			</File>
+			<File
+				RelativePath=".\ldecod\inc\quant.h">
+			</File>
 			<File
 				RelativePath=".\ldecod\inc\rtp.h">
 			</File>
diff --git a/ldecod_vc8.vcproj b/ldecod_vc8.vcproj
index 35d855b..beb71e5 100644
--- a/ldecod_vc8.vcproj
+++ b/ldecod_vc8.vcproj
@@ -4,6 +4,7 @@
 	Version="8.00"
 	Name="ldecod"
 	ProjectGUID="{5499B067-CF32-4141-A757-E0A29866994A}"
+	RootNamespace="ldecod"
 	>
 	<Platforms>
 		<Platform
@@ -324,6 +325,10 @@
 				RelativePath=".\ldecod\src\parsetcommon.c"
 				>
 			</File>
+			<File
+				RelativePath=".\ldecod\src\quant.c"
+				>
+			</File>
 			<File
 				RelativePath=".\ldecod\src\rtp.c"
 				>
@@ -469,6 +474,10 @@
 				RelativePath=".\ldecod\inc\parsetcommon.h"
 				>
 			</File>
+			<File
+				RelativePath=".\ldecod\inc\quant.h"
+				>
+			</File>
 			<File
 				RelativePath=".\ldecod\inc\rtp.h"
 				>
diff --git a/lencod/inc/block.h b/lencod/inc/block.h
index 05636c7..2fe9352 100644
--- a/lencod/inc/block.h
+++ b/lencod/inc/block.h
@@ -18,9 +18,6 @@
 #ifndef _BLOCK_H_
 #define _BLOCK_H_
 
-//! make chroma QP from quant
-extern const byte QP_SCALE_CR[52] ;
-
 
 //! single scan pattern
 const byte SNGL_SCAN[16][2] =
@@ -48,6 +45,14 @@ const byte COEFF_COST4x4[2][16] =
   {9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9}
 };
 
+const byte SCAN_YUV420  [4][2] =
+{
+  {0,0},
+  {0,1},
+  {0,2},
+  {0,3}
+};
+
 //! single scan pattern
 const byte SCAN_YUV422  [8][2] =
 {
@@ -57,58 +62,79 @@ const byte SCAN_YUV422  [8][2] =
   {1,2},{1,3}
 };
 
+
 //! look up tables for FRExt-chroma support
-const unsigned char hor_offset[4][4][4] =
-  {{{0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 4, 0, 4},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 4, 0, 4},
-  {0, 4, 0, 4},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 4, 0, 4},
-  {8,12, 8,12},
-  {0, 4, 0, 4},
-  {8,12, 8,12}}};
-
-const unsigned char ver_offset[4][4][4] =
-  { {{0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 0, 4, 4},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 0, 4, 4},
-  {8, 8,12,12},
-  {0, 0, 0, 0},
-  {0, 0, 0, 0}},
-
-  {{0, 0, 4, 4},
-  {0, 0, 4, 4},
-  {8, 8,12,12},
-  {8, 8,12,12}}};
-
-static unsigned char cbp_blk_chroma[8][4] =
-  { {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} };
+const unsigned char hor_offset[4][4][4] =  {
+  {
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 4, 0, 4},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 4, 0, 4},
+    {0, 4, 0, 4},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 4, 0, 4},
+    {8,12, 8,12},
+    {0, 4, 0, 4},
+    {8,12, 8,12}
+  }
+};
+
+const unsigned char ver_offset[4][4][4] =  { 
+  {
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 0, 4, 4},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 0, 4, 4},
+    {8, 8,12,12},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0}
+  },
+  {
+    {0, 0, 4, 4},
+    {0, 0, 4, 4},
+    {8, 8,12,12},
+    {8, 8,12,12}
+  }
+};
+
+static const int A[4][4] = {
+  { 16, 20, 16, 20},
+  { 20, 25, 20, 25},
+  { 16, 20, 16, 20},
+  { 20, 25, 20, 25}
+};
+
+static unsigned char cbp_blk_chroma[8][4] = {
+  {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} 
+};
 
 #endif
 
diff --git a/lencod/inc/cconv_yuv2rgb.h b/lencod/inc/cconv_yuv2rgb.h
new file mode 100644
index 0000000..f5e971e
--- /dev/null
+++ b/lencod/inc/cconv_yuv2rgb.h
@@ -0,0 +1,26 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    cconv_yuv2rgb.h
+ *
+ * \author
+ *    Woo-Shik Kim
+ *
+ * \date
+ *    29 May 2008
+ *
+ * \brief
+ *    Headerfile for YUV to RGB color conversion
+ **************************************************************************
+ */
+
+#ifndef _CCONV_YUV2RGB_H_
+#define _CCONV_YUV2RGB_H_
+
+#include "img_distortion.h"
+
+void init_YUVtoRGB(void);
+void YUVtoRGB(ImageStructure *YUV, ImageStructure *RGB);
+
+#endif
+
diff --git a/lencod/inc/configfile.h b/lencod/inc/configfile.h
index 5652be8..a0c5ece 100644
--- a/lencod/inc/configfile.h
+++ b/lencod/inc/configfile.h
@@ -71,7 +71,7 @@ Mapping Map[] = {
     {"ResendPPS",                &configinput.ResendPPS,                    0,   0.0,                       1,  0.0,              1.0              },
     {"SourceWidth",              &configinput.source.width,                 0,   176.0,                     2, 16.0,              0.0              },
     {"SourceHeight",             &configinput.source.height,                0,   144.0,                     2, 16.0,              0.0              },
-    {"SourceResize",             &configinput.src_resize,                   0,     0.0,                     1,  0.0,              1.0              },
+    {"SourceResize",             &configinput.src_resize,                   0,   0.0,                       1,  0.0,              1.0              },
     {"OutputWidth",              &configinput.output.width,                 0,   176.0,                     2, 16.0,              0.0              },
     {"OutputHeight",             &configinput.output.height,                0,   144.0,                     2, 16.0,              0.0              },
     {"MbLineIntraUpdate",        &configinput.intra_upd,                    0,   0.0,                       1,  0.0,              1.0              },
@@ -128,7 +128,7 @@ Mapping Map[] = {
     {"Intra4x4DirDisable",       &configinput.Intra4x4DirDisable,           0,   0.0,                       1,  0.0,              1.0              },
     {"Intra16x16ParDisable",     &configinput.Intra16x16ParDisable,         0,   0.0,                       1,  0.0,              1.0              },
     {"Intra16x16PlaneDisable",   &configinput.Intra16x16PlaneDisable,       0,   0.0,                       1,  0.0,              1.0              },
-    {"EnableIPCM",               &configinput.EnableIPCM,                   0,   1.0,                       1,  0.0,              1.0              },
+    {"EnableIPCM",               &configinput.EnableIPCM,                   0,   0.0,                       1,  0.0,              1.0              },
     {"ChromaIntraDisable",       &configinput.ChromaIntraDisable,           0,   0.0,                       1,  0.0,              1.0              },
     // For future use
     {"FastMDEnable",             &configinput.FastMDEnable,                 0,   0.0,                       1,  0.0,              0.0              },           
@@ -149,6 +149,10 @@ Mapping Map[] = {
     {"ChangeQPStart",            &configinput.qp2start,                     0,   0.0,                       2,  0.0,              0.0              },
 #endif
     {"RDOptimization",           &configinput.rdopt,                        0,   0.0,                       1,  0.0,              3.0              },
+    {"DistortionSSIM",           &configinput.Distortion[SSIM],             0,   0.0,                       1,  0.0,              1.0              },
+    {"DistortionMS_SSIM",        &configinput.Distortion[MS_SSIM],          0,   0.0,                       1,  0.0,              1.0              },
+    {"SSIMOverlapSize",          &configinput.SSIMOverlapSize,              0,   1.0,                       2,  1.0,              1.0              },
+    {"DistortionYUVtoRGB",       &configinput.DistortionYUVtoRGB,           0,   0.0,                       1,  0.0,              1.0              },
     {"CtxAdptLagrangeMult",      &configinput.CtxAdptLagrangeMult,          0,   0.0,                       1,  0.0,              1.0              },
     {"FastCrIntraDecision",      &configinput.FastCrIntraDecision,          0,   0.0,                       1,  0.0,              1.0              },
     {"DisableThresholding",      &configinput.disthres,                     0,   0.0,                       1,  0.0,              1.0              },
@@ -157,6 +161,7 @@ Mapping Map[] = {
     {"LossRateB",                &configinput.LossRateB,                    0,   0.0,                       2,  0.0,              0.0              },
     {"LossRateC",                &configinput.LossRateC,                    0,   0.0,                       2,  0.0,              0.0              },
     {"NumberOfDecoders",         &configinput.NoOfDecoders,                 0,   0.0,                       2,  0.0,              0.0              },
+    {"ErrorConcealment",         &configinput.ErrorConcealment,             0,   0.0,                       2,  0.0,              0.0              },
     {"RestrictRefFrames",        &configinput.RestrictRef ,                 0,   0.0,                       1,  0.0,              1.0              },
 #ifdef _LEAKYBUCKET_
     {"NumberofLeakyBuckets",     &configinput.NumberLeakyBuckets,           0,   2.0,                       1,  2.0,              255.0            },
@@ -168,10 +173,13 @@ Mapping Map[] = {
 
     {"IntraBottom",              &configinput.IntraBottom,                  0,   0.0,                       1,  0.0,              1.0              },
 
-    {"NumberFramesInEnhancementLayerSubSequence", &configinput.NumFramesInELSubSeq, 0,   0.0,               2,  0.0,              0.0              },
+    {"NumFramesInELayerSubSeq",  &configinput.NumFramesInELSubSeq,          0,   0.0,                       2,  0.0,              0.0              },
     {"RandomIntraMBRefresh",     &configinput.RandomIntraMBRefresh,         0,   0.0,                       2,  0.0,              0.0              },
     {"WeightedPrediction",       &configinput.WeightedPrediction,           0,   0.0,                       1,  0.0,              1.0              },
     {"WeightedBiprediction",     &configinput.WeightedBiprediction,         0,   0.0,                       1,  0.0,              2.0              },
+    {"WPMethod",                 &configinput.WPMethod,                     0,   0.0,                       1,  0.0,              1.0              }, 
+    {"ChromaWeightSupport",      &configinput.ChromaWeightSupport,          0,   0.0,                       1,  0.0,              1.0              },    
+    {"EnhancedBWeightSupport",   &configinput.EnhancedBWeightSupport,       0,   0.0,                       1,  0.0,              1.0              },    
     {"UseWeightedReferenceME",   &configinput.UseWeightedReferenceME,       0,   0.0,                       1,  0.0,              1.0              },
     {"RDPictureDecision",        &configinput.RDPictureDecision,            0,   0.0,                       1,  0.0,              1.0              },
     {"RDPictureIntra",           &configinput.RDPictureIntra,               0,   0.0,                       1,  0.0,              1.0              },
@@ -189,6 +197,11 @@ Mapping Map[] = {
 
     //Bipredicting Motion Estimation parameters
     {"BiPredMotionEstimation",   &configinput.BiPredMotionEstimation,       0,   0.0,                       1,  0.0,              1.0              },
+    {"BiPredSearch16x16",        &configinput.BiPredSearch[0],              0,   1.0,                       1,  0.0,              1.0              },
+    {"BiPredSearch16x8",         &configinput.BiPredSearch[1],              0,   0.0,                       1,  0.0,              1.0              },
+    {"BiPredSearch8x16",         &configinput.BiPredSearch[2],              0,   0.0,                       1,  0.0,              1.0              },
+    {"BiPredSearch8x8",          &configinput.BiPredSearch[3],              0,   0.0,                       1,  0.0,              1.0              },
+    
     {"BiPredMERefinements",      &configinput.BiPredMERefinements,          0,   0.0,                       1,  0.0,              5.0              },
     {"BiPredMESearchRange",      &configinput.BiPredMESearchRange,          0,   8.0,                       2,  0.0,              0.0              },
     {"BiPredMESubPel",           &configinput.BiPredMESubPel,               0,   1.0,                       1,  0.0,              2.0              },
@@ -256,12 +269,13 @@ Mapping Map[] = {
     {"MEDistortionHPel",         &configinput.MEErrorMetric[H_PEL],         0,   0.0,                       1,  0.0,              3.0              },
     {"MEDistortionQPel",         &configinput.MEErrorMetric[Q_PEL],         0,   0.0,                       1,  0.0,              3.0              },
     {"MDDistortion",             &configinput.ModeDecisionMetric,           0,   2.0,                       1,  0.0,              2.0              },
+    {"SkipDeBlockNonRef",        &configinput.SkipDeBlockNonRef,            0,   0.0,                       1,  0.0,              1.0              },
 
     // Rate Control
     {"RateControlEnable",        &configinput.RCEnable,                     0,   0.0,                       1,  0.0,              1.0              },
     {"Bitrate",                  &configinput.bit_rate,                     0,   0.0,                       2,  0.0,              0.0              },
     {"InitialQP",                &configinput.SeinitialQP,                  0,   0.0,                       3,  (double) MIN_QP,  (double) MAX_QP  },
-    {"BasicUnit",                &configinput.basicunit,                    0,   1.0,                       2,  1.0,              0.0              },
+    {"BasicUnit",                &configinput.basicunit,                    0,   0.0,                       2,  0.0,              0.0              },
     {"ChannelType",              &configinput.channel_type,                 0,   0.0,                       1,  0.0,              1.0              },
     {"RCUpdateMode",             &configinput.RCUpdateMode,                 0,   0.0,                       1,  0.0,              4.0              },
     {"RCISliceBitRatio",         &configinput.RCISliceBitRatio,             2,   1.0,                       1,  0.0,              20.0             },
@@ -307,7 +321,7 @@ Mapping Map[] = {
 // New Input bit-depth entries
     {"SourceBitDepthLuma",       &configinput.source.bit_depth[0],          0,   8.0,                       1,  8.0,             14.0              },
     {"SourceBitDepthChroma",     &configinput.source.bit_depth[1],          0,   8.0,                       1,  8.0,             14.0              },
-    {"SourceBitDepthRescale",    &configinput.src_BitDepthRescale,          0,   1.0,                       1,  0.0,              1.0              },
+    {"SourceBitDepthRescale",    &configinput.src_BitDepthRescale,          0,   0.0,                       1,  0.0,              1.0              },
 // Old variables replaced from BitDepthLuma and BitDepthChroma. Considered only if SourceBitDepthRescale is 1.
     {"OutputBitDepthLuma",       &configinput.output.bit_depth[0],          0,   8.0,                       1,  8.0,             14.0              },
     {"OutputBitDepthChroma",     &configinput.output.bit_depth[1],          0,   8.0,                       1,  8.0,             14.0              },
@@ -323,6 +337,7 @@ Mapping Map[] = {
 
     // Explicit Lambda Parameters for RDO
     {"UseExplicitLambdaParams",  &configinput.UseExplicitLambdaParams,      0,   0.0,                       1,  0.0,              3.0              },
+    {"UpdateLambdaChromaME",     &configinput.UpdateLambdaChromaME,         0,   0.0,                       1,  0.0,              3.0              },    
     {"FixedLambdaPSlice",        &configinput.FixedLambda[0],               2,   0.1,                       2,  0.0,              0.0              },
     {"FixedLambdaBSlice",        &configinput.FixedLambda[1],               2,   0.1,                       2,  0.0,              0.0              },
     {"FixedLambdaISlice",        &configinput.FixedLambda[2],               2,   0.1,                       2,  0.0,              0.0              },
@@ -378,6 +393,7 @@ Mapping Map[] = {
     {"EPZSFixedPredictors",      &configinput.EPZSFixed,                    0,   2.0,                       1,  0.0,              2.0              },
     {"EPZSTemporal",             &configinput.EPZSTemporal,                 0,   1.0,                       1,  0.0,              1.0              },
     {"EPZSSpatialMem",           &configinput.EPZSSpatialMem,               0,   1.0,                       1,  0.0,              1.0              },
+    {"EPZSBlockType",            &configinput.EPZSBlockType,                0,   1.0,                       1,  0.0,              1.0              },
     {"EPZSMinThresScale",        &configinput.EPZSMinThresScale,            0,   0.0,                       0,  0.0,              0.0              },
     {"EPZSMaxThresScale",        &configinput.EPZSMaxThresScale,            0,   2.0,                       0,  0.0,              0.0              },
     {"EPZSMedThresScale",        &configinput.EPZSMedThresScale,            0,   1.0,                       0,  0.0,              0.0              },
@@ -394,7 +410,9 @@ Mapping Map[] = {
     {"WeightY",                  &configinput.WeightY,                      2,   1.00,                      1,  0.0,              4.0              },
     {"WeightCb",                 &configinput.WeightCb,                     2,   1.00,                      1,  0.0,              4.0              },
     {"WeightCr",                 &configinput.WeightCr,                     2,   1.00,                      1,  0.0,              4.0              },
-
+    {"WPMCPrecision",            &configinput.WPMCPrecision,                0,   0.0,                       1,  0.0,              2.0              },
+    {"WPMCPrecFullRef",          &configinput.WPMCPrecFullRef,              0,   0.0,                       1,  0.0,              1.0              },
+    {"WPMCPrecBSlice",           &configinput.WPMCPrecBSlice,               0,   1.0,                       1,  0.0,              2.0              },
 
     // Trellis based quantization
     {"UseRDOQuant",              &configinput.UseRDOQuant,                  0,   0.0,                       1,  0.0,              1.0              },
diff --git a/lencod/inc/conformance.h b/lencod/inc/conformance.h
index c3013be..9c6c204 100644
--- a/lencod/inc/conformance.h
+++ b/lencod/inc/conformance.h
@@ -1,7 +1,7 @@
 
 /*!
  ************************************************************************
- * \file comformance.h
+ * \file conformance.h
  *
  * \brief
  *   Level & Profile Related definitions  
diff --git a/lencod/inc/defines.h b/lencod/inc/defines.h
index a352a0a..de64884 100644
--- a/lencod/inc/defines.h
+++ b/lencod/inc/defines.h
@@ -6,8 +6,11 @@
  *    Header file containing some useful global definitions
  *
  * \author
- *    Detlev Marpe
- *    Copyright (C) 2000 HEINRICH HERTZ INSTITUTE All Rights Reserved.
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Detlev Marpe
+ *     - Karsten Sühring                 <suehring@hhi.de> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
+ *   
  *
  * \date
  *    21. March 2001
@@ -24,6 +27,10 @@
 #define TRACE               0       //!< 0:Trace off 1:Trace on 2:detailed CABAC context information
 #endif
 
+#define JM                  "14 (FRExt)"
+#define VERSION             "14.1"
+#define EXT_VERSION         "(FRExt)"
+
 #define GET_METIME          1       //!< Enables or disables ME computation time
 #define DUMP_DPB            0       //!< Dump DPB for debug purposes
 #define IMGTYPE             1       //!< Define imgpel size type. 0 implies byte (cannot handle >8 bit depths) and 1 implies unsigned short
@@ -47,7 +54,7 @@
 #define FREXT_Hi444     244      //!< YUV 4:4:4/14 "High 4:4:4"
 #define FREXT_CAVLC444   44      //!< YUV 4:4:4/14 "CAVLC 4:4:4"
 
-#define ZEROSNR 1
+#define ZEROSNR           1
 
 // CAVLC
 enum {
@@ -170,6 +177,7 @@ enum {
 #define BLOCK_SIZE_8x8         8
 #define MB_BLOCK_SIZE         16
 #define MB_PIXELS            256 //(MB_BLOCK_SIZE * MB_BLOCK_SIZE)
+#define MB_PIXELS_SHIFT        8 // log2(MB_BLOCK_SIZE * MB_BLOCK_SIZE)
 #define MB_BLOCK_SHIFT         4
 #define BLOCK_MULTIPLE         4  //(MB_BLOCK_SIZE/BLOCK_SIZE)
 #define MB_BLOCK_PARTITIONS   16  //(BLOCK_MULTIPLE * BLOCK_MULTIPLE)
diff --git a/lencod/inc/enc_statistics.h b/lencod/inc/enc_statistics.h
new file mode 100644
index 0000000..c98fb92
--- /dev/null
+++ b/lencod/inc/enc_statistics.h
@@ -0,0 +1,64 @@
+/*!
+ **************************************************************************
+ *  \file enc_statistics.h
+ *
+ *  \brief
+ *     statistics reports for the encoding process.
+ *
+ *  \author
+ *      Main contributors (see contributors.h for copyright, address and affiliation details)
+ *      - Alexis Tourapis                 <alexismt@ieee.org>
+ *      - Karsten Sühring                 <suehring@hhi.de>
+ *
+ **************************************************************************
+ */
+
+#ifndef _ENC_STATISTICS_H_
+#define _ENC_STATISTICS_H_
+#include "global.h"
+
+ typedef struct
+ {
+   int   quant0;                      //!< quant for the first frame
+   int   quant1;                      //!< average quant for the remaining frames
+   float bitr;                        //!< bit rate for current frame, used only for output til terminal
+   float bitrate;                     //!< average bit rate for the sequence except first frame
+   int64 bit_ctr;                     //!< counter for bit usage
+   int64 bit_ctr_n;                   //!< bit usage for the current frame
+   int   bit_slice;                   //!< number of bits in current slice
+   int   stored_bit_slice;            //!< keep number of bits in current slice (to restore status in case of MB re-encoding)
+   int   bit_ctr_emulationprevention; //!< stored bits needed to prevent start code emulation
+   int   b8_mode_0_use     [NUM_SLICE_TYPES][2];
+   int64 mode_use_transform[NUM_SLICE_TYPES][MAXMODE][2];
+   int   intra_chroma_mode[4];
+
+   // B pictures
+   int     successive_Bframe;
+   int     *mode_use_Bframe;
+   int     *bit_use_mode_Bframe;
+
+   int     frame_counter;
+   int     frame_ctr           [NUM_SLICE_TYPES];
+   int64   bit_counter[NUM_SLICE_TYPES];
+   float   bitrate_st [NUM_SLICE_TYPES];
+   int64   mode_use            [NUM_SLICE_TYPES][MAXMODE]; //!< Macroblock mode usage for Intra frames
+   int64   bit_use_mode        [NUM_SLICE_TYPES][MAXMODE]; //!< statistics of bit usage
+   int64   bit_use_stuffingBits[NUM_SLICE_TYPES];
+   int64   bit_use_mb_type     [NUM_SLICE_TYPES];
+   int64   bit_use_header      [NUM_SLICE_TYPES];
+   int64   tmp_bit_use_cbp     [NUM_SLICE_TYPES];
+   int64   bit_use_coeffC      [NUM_SLICE_TYPES];
+   int64   bit_use_coeff    [3][NUM_SLICE_TYPES];  
+   int64   bit_use_delta_quant [NUM_SLICE_TYPES];
+
+   int   em_prev_bits_frm;
+   int   em_prev_bits_fld;
+   int  *em_prev_bits;
+   int   bit_ctr_parametersets;
+   int   bit_ctr_parametersets_n;
+ } StatParameters;
+
+ extern StatParameters *stats;
+
+#endif
+
diff --git a/lencod/inc/errdo.h b/lencod/inc/errdo.h
new file mode 100644
index 0000000..ba26337
--- /dev/null
+++ b/lencod/inc/errdo.h
@@ -0,0 +1,34 @@
+/*!
+ **************************************************************************
+ *  \file errdo.h
+ *  \brief  Header file for error resilient RDO (name of file should change)
+ *
+ *  \author 
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Peshala Pahalawatta                     <ppaha@dolby.com>
+ *    - Alexis Michael Tourapis                 <atour@ieee.org>
+ *
+ **************************************************************************
+ */
+
+#ifndef _ERRDO_H_
+#define _ERRDO_H_
+
+//============= rate-distortion opt with packet losses ===========
+
+void init_error_conceal(int concealment_type);
+
+void compute_residue_block (ImageParameters *image, imgpel **imgY, int res_img[16][16], imgpel mb_pred[16][16], int b8block, int block_size);
+
+void decode_one_b8block (ImageParameters *image, StorablePicture *enc_pic, int decoder, int mbmode, int block8x8, short mv_mode, short b8ref);
+void decode_one_mb  (ImageParameters *image, StorablePicture *enc, int decoder, Macroblock* currMB);
+void UpdateDecoders (InputParameters *params, ImageParameters *image, StorablePicture *enc_pic);
+
+void (*error_conceal_picture)(ImageParameters *image, StorablePicture *enc_pic, int decoder);
+void copy_conceal_picture(ImageParameters *image, StorablePicture *enc_pic, int decoder);
+
+void errdo_store_best_block(ImageParameters* image, imgpel*** mbY, imgpel*** dec_img, int j0, int i0, int block_size);
+void errdo_get_best_block(ImageParameters* image, imgpel*** dec_img, imgpel*** mbY, int j0, int block_size);
+
+#endif
+
diff --git a/lencod/inc/errdo_mc_prediction.h b/lencod/inc/errdo_mc_prediction.h
new file mode 100644
index 0000000..683a27c
--- /dev/null
+++ b/lencod/inc/errdo_mc_prediction.h
@@ -0,0 +1,35 @@
+/*!
+ *************************************************************************************
+ * \file errd_mc_prediction.h
+ *
+ * \brief
+ *    definitions for motion compensated prediction
+ *
+ * \author
+ *      Main contributors (see contributors.h for copyright, 
+ *                         address and affiliation details)
+ *      - Alexis Michael Tourapis  <alexismt@ieee.org>
+ *      - Modified for use in hypothetical decoders at encoder
+ *           by Peshala V. Pahalawatta <pesh@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+#ifndef _ERRDO_MC_PREDICTION_H_
+#define _ERRDO_MC_PREDICTION_H_
+
+#include "global.h"
+#include "mbuffer.h"
+
+//extern StorablePicture *enc_picture;
+
+extern void get_block_luma(int decoder, ColorPlane pl, StorablePicture *dec_picture, StorablePicture *list, int x_pos, int y_pos, int ver_block_size, int hor_block_size, ImageParameters *img, imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE]);
+extern void get_block_chroma(int decoder, int uv, StorablePicture *dec_picture, StorablePicture *list, int x_pos, int y_pos, int hor_block_size, int ver_block_size, ImageParameters *img, imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE]);
+
+//extern void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int smb);
+//extern void prepare_direct_params(Macroblock *currMB, StorablePicture *dec_picture, ImageParameters *img, short pmvl0[2], short pmvl1[2],char *l0_rFrame, char *l1_rFrame);
+
+extern void perform_mc(int decoder, ColorPlane pl, StorablePicture *dec_picture, ImageParameters *img, int pred_dir, int l0_mode, int l1_mode, int i, int j, int list_offset, int block_size_x, int block_size_y, int curr_mb_field);
+extern void perform_mc_concealment(int decoder, ColorPlane pl, StorablePicture *dec_picture, ImageParameters *img, int pred_dir, int i, int j, int block_size_x, int block_size_y);
+#endif
+
diff --git a/lencod/inc/filehandle.h b/lencod/inc/filehandle.h
new file mode 100644
index 0000000..fdbaf26
--- /dev/null
+++ b/lencod/inc/filehandle.h
@@ -0,0 +1,25 @@
+
+/*!
+ ***************************************************************************
+ *
+ * \file filehandle.h
+ *
+ * \brief
+ *
+ * \date
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *
+ **************************************************************************/
+
+#ifndef _FILEHANDLE_H_
+#define _FILEHANDLE_H_
+
+int  rewrite_paramsets(void);
+int  start_sequence(void);
+int  terminate_sequence(void);
+int  write_PPS(int, int);
+
+
+#endif
diff --git a/lencod/inc/frame.h b/lencod/inc/frame.h
index 1407c3f..40c53ce 100644
--- a/lencod/inc/frame.h
+++ b/lencod/inc/frame.h
@@ -21,9 +21,13 @@ typedef struct
   int height;                        //!< luma component frame height    
   int height_cr;                     //!< chroma component frame width
   int width_cr;                      //!< chroma component frame height
+  int mb_width;                      //!< luma component frame width
+  int mb_height;                     //!< luma component frame height    
   int size_cmp[3];                   //!< component sizes  
   int size;                          //!< total image size
   int bit_depth[3];                  //!< component bit depth  
+  int max_value[3];                  //!< component max value
+  int max_value_sq[3];                  //!< component max value squared
 } FrameFormat;
 
 #endif
diff --git a/lencod/inc/global.h b/lencod/inc/global.h
index fccadb6..a238c5f 100644
--- a/lencod/inc/global.h
+++ b/lencod/inc/global.h
@@ -8,20 +8,7 @@
  *     global definitions for H.264 encoder.
  *
  *  \author
- *     Copyright (C) 1999  Telenor Satellite Services,Norway
- *                         Ericsson Radio Systems, Sweden
- *
- *     Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
- *
- *     Telenor Satellite Services
- *     Keysers gt.13                       tel.:   +47 23 13 86 98
- *     N-0130 Oslo,Norway                  fax.:   +47 22 77 79 80
- *
- *     Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
- *
- *     Ericsson Radio Systems
- *     KI/ERA/T/VV
- *     164 80 Stockholm, Sweden
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
  *
  ************************************************************************
  */
@@ -206,7 +193,8 @@ typedef enum
   B_SLICE = 1,
   I_SLICE = 2,
   SP_SLICE = 3,
-  SI_SLICE = 4
+  SI_SLICE = 4,
+  NUM_SLICE_TYPES = 5
 } SliceType;
 
 //Motion Estimation levels
@@ -410,15 +398,14 @@ typedef struct macroblock
   int64               cbp_bits[3];
   int64               cbp_bits_8x8[3];
 
-  short               bi_pred_me;
+  short               bipred_me[4]; //!< bi prediction ME type for a 8x8 block (0 : not used, 1: type 1, 2: type 2)
 
   // rate control
   double              actj;               // macroblock activity measure for macroblock j
   int                 prev_qp;
   int                 prev_dqp;
   int                 prev_cbp;
-  int                 predict_qp;
-  int                 predict_error;
+
 
   struct macroblock   *mb_available_up;   //!< pointer to neighboring MB (CABAC)
   struct macroblock   *mb_available_left; //!< pointer to neighboring MB (CABAC)
@@ -464,6 +451,7 @@ typedef struct
 {
   int                 picture_id;
   int                 qp;
+  int                 qs;
   int                 picture_type; //!< picture type
   int                 start_mb_nr;
   int                 max_part_nr;  //!< number of different partitions
@@ -490,6 +478,33 @@ typedef struct
 
 
 #define MAXSLICEPERPICTURE 100
+
+enum {
+  SSE              = 0,
+  SSE_RGB          = 1,  
+  PSNR             = 2,
+  PSNR_RGB         = 3,
+  SSIM             = 4,
+  SSIM_RGB         = 5,
+  MS_SSIM          = 6,
+  MS_SSIM_RGB      = 7,
+  TOTAL_DIST_TYPES = 8
+} distortion_types;
+
+//! DistortionParams
+typedef struct
+{
+  float value[3];                   //!< current frame distortion
+  float average[3];                 //!< average frame distortion
+  float avslice[NUM_SLICE_TYPES][3]; //!< average frame type distortion
+} DistMetric;
+
+typedef struct
+{
+  int        frame_ctr;                        //!< number of coded frames
+  DistMetric metric[TOTAL_DIST_TYPES];      //!< Distortion metrics
+} DistortionParams;
+
 typedef struct
 {
   int   no_slices;
@@ -497,9 +512,7 @@ typedef struct
   int bits_per_picture;
   Slice *slices[MAXSLICEPERPICTURE];
 
-  float distortion_y;
-  float distortion_u;
-  float distortion_v;
+  DistMetric distortion;
 } Picture;
 
 Picture *p_frame_pic;
@@ -514,10 +527,8 @@ long *Bit_Buffer;
 // global picture format dependend buffers, mem allocation in image.c
 imgpel **pImgOrg[MAX_PLANE];
 imgpel **pCurImg;            //!< Reference image. Luma for other profiles, can be any component for 4:4:4
-imgpel ***imgUV_org;         //!< Reference chroma image
 int    **imgY_sub_tmp;       //!< Y picture temporary component (Quarter pel)
 
-
 int **PicPos;
 unsigned int log2_max_frame_num_minus4;
 unsigned int log2_max_pic_order_cnt_lsb_minus4;
@@ -548,17 +559,11 @@ int wp_luma_round;
 int wp_chroma_round;
 
 // global picture format dependend buffers, mem allocation in image.c (field picture)
-imgpel   **imgY_org_top;
-imgpel   **imgY_org_bot;
-
-imgpel  ***imgUV_org_top;
-imgpel  ***imgUV_org_bot;
-
-imgpel   **imgY_org_frm;
-imgpel  ***imgUV_org_frm;
+imgpel   **img_org_top[MAX_PLANE];
+imgpel   **img_org_bot[MAX_PLANE];
+imgpel   **img_org_frm[MAX_PLANE];
 
 imgpel   **imgY_com;               //!< Encoded luma images
-imgpel   **imgY_org_frm_JV[MAX_PLANE];  //!< imgY_org_frm to be used during 4:4:4 independent mode encoding
 imgpel  ***imgUV_com;              //!< Encoded croma images
 
 char    ***direct_ref_idx;           //!< direct mode reference index buffer
@@ -569,7 +574,6 @@ byte **pixel_map;   //!< Shows the latest reference frame that is reliable for e
 byte **refresh_map; //!< Stores the new values for pixel_map
 int intras;         //!< Counts the intra updates in each frame.
 
-int  frame_ctr[5];
 int  frame_no, nextP_tr_fld, nextP_tr_frm;
 
 time_t  tot_time;
@@ -583,42 +587,22 @@ char b8_ipredmode8x8[4][4], b8_intra_pred_modes8x8[16];
 //! Info for the "decoders-in-the-encoder" used for rdoptimization with packet losses
 typedef struct
 {
-  int  **resY;               //!< Residue of Luminance
-  imgpel ***decY;            //!< Decoded values at the simulated decoders
-  imgpel ****decref;         //!< Reference frames of the simulated decoders
-  imgpel ***decY_best;       //!< Decoded frames for the best mode for all decoders
-  imgpel **RefBlock;
-  byte **status_map;
-  byte **dec_mb_mode;
+  imgpel ***dec_mbY;        //!< Best decoded macroblock pixel values in RDO
+  imgpel ***dec_mbY8x8;     //!< Best decoded 8x8 mode pixel values in RDO
+  int    res_img[MAX_PLANE][16][16]; //Residual values for macroblock
 } Decoders;
 extern Decoders *decs;
 
-//! SNRParameters
-typedef struct
-{
-  float snr_y;               //!< current Y SNR
-  float snr_u;               //!< current U SNR
-  float snr_v;               //!< current V SNR
-  float snr_y1;              //!< SNR Y(dB) first frame
-  float snr_u1;              //!< SNR U(dB) first frame
-  float snr_v1;              //!< SNR V(dB) first frame
-  float snr_yt[5];           //!< SNR Y(dB) based on frame type
-  float snr_ut[5];           //!< SNR U(dB) based on frame type
-  float snr_vt[5];           //!< SNR V(dB) based on frame type
-  float snr_ya;              //!< Average SNR Y(dB) remaining frames
-  float snr_ua;              //!< Average SNR U(dB) remaining frames
-  float snr_va;              //!< Average SNR V(dB) remaining frames
-  float sse_y;               //!< SSE Y
-  float sse_u;               //!< SSE U
-  float sse_v;               //!< SSE V
-  float msse_y;              //!< Average SSE Y
-  float msse_u;              //!< Average SSE U
-  float msse_v;              //!< Average SSE V
-  int   frame_ctr;           //!< number of coded frames
-} SNRParameters;
 
 #define FILE_NAME_SIZE 200
 
+typedef struct
+{
+  double md;     //!< Mode decision Lambda
+  double me[3];  //!< Motion Estimation Lambda
+  int    mf[3];  //!< Integer formatted Motion Estimation Lambda
+} LambdaParams;
+
 // VUI Parameters
 typedef struct
 {
@@ -676,7 +660,18 @@ typedef struct
   int max_dec_frame_buffering;
 } VUIParameters;
 
-                             //! all input parameters
+//! block 8x8 temporary RD info
+typedef struct 
+{
+   short  best8x8mode            [4];
+   char   best8x8pdir   [MAXMODE][4];
+   char   best8x8l0ref  [MAXMODE][4];
+   char   best8x8l1ref  [MAXMODE][4];
+   short  bipred8x8me   [MAXMODE][4];
+} Block8x8Info;
+
+                             
+//! all input parameters
 typedef struct
 {
   int ProfileIDC;                    //!< value of syntax element profile_idc
@@ -749,7 +744,9 @@ typedef struct
   int directInferenceFlag;           //!< Direct Mode Inference Flag
 
   int BiPredMotionEstimation;
-  int BiPredMERefinements;
+  int BiPredSearch[4];               //!< Use Bi prediction for modes 16x16, 16x8, 8x16, and 8x8
+  
+  int BiPredMERefinements;           //!< Number of bipred refinements
   int BiPredMESearchRange;
   int BiPredMESubPel;
 
@@ -767,7 +764,12 @@ typedef struct
 
   int WeightedPrediction;            //!< Weighted prediction for P frames (0: not used, 1: explicit)
   int WeightedBiprediction;          //!< Weighted prediction for B frames (0: not used, 1: explicit, 2: implicit)
-  int WPMethod;
+  int WPMethod;                      //!< WP method (0: DC, 1: LMS)
+  int WPMCPrecision;
+  int WPMCPrecFullRef;
+  int WPMCPrecBSlice;
+  int EnhancedBWeightSupport;
+  int ChromaWeightSupport;           //!< Weighted prediction support for chroma (0: disabled, 1: enabled)
   int UseWeightedReferenceME;        //!< Use Weighted Reference for ME.
   int RDPictureDecision;             //!< Perform RD optimal decision between various coded versions of same picture
   int RDPictureIntra;                //!< Enabled RD pic decision for intra as well.
@@ -814,6 +816,7 @@ typedef struct
   int EPZSFixed;
   int EPZSTemporal;
   int EPZSSpatialMem;
+  int EPZSBlockType;
   int EPZSMinThresScale;
   int EPZSMaxThresScale;
   int EPZSMedThresScale;
@@ -835,6 +838,10 @@ typedef struct
   int qp02, qpBRS2Offset;
 #endif
   int rdopt;
+  int Distortion[TOTAL_DIST_TYPES];
+  double VisualResWavPSNR;
+  int SSIMOverlapSize;
+  int DistortionYUVtoRGB;
   int CtxAdptLagrangeMult;    //!< context adaptive lagrangian multiplier
   int FastCrIntraDecision;
   int disthres;
@@ -855,15 +862,16 @@ typedef struct
   int LossRateB;              //!< assumed loss probablility of partition B, in per cent, used for loss-aware R/D
   int LossRateC;              //!< assumed loss probablility of partition C, in per cent, used for loss-aware R/D
   int NoOfDecoders;
+  int ErrorConcealment;       //!< Error concealment method used for loss-aware RDO (0: Copy Concealment)
   int RestrictRef;
   int NumFramesInELSubSeq;
 
   int RandomIntraMBRefresh;     //!< Number of pseudo-random intra-MBs per picture
 
   int DFSendParameters;
-  int DFDisableIdc[2][5];
-  int DFAlpha[2][5];
-  int DFBeta[2][5];
+  int DFDisableIdc[2][NUM_SLICE_TYPES];
+  int DFAlpha     [2][NUM_SLICE_TYPES];
+  int DFBeta      [2][NUM_SLICE_TYPES];
 
   int SparePictureOption;
   int SPDetectionThreshold;
@@ -904,8 +912,8 @@ typedef struct
   double RCBoverPRatio;
   double RCISliceBitRatio;
   double RCBSliceBitRatio[RC_MAX_TEMPORAL_LEVELS];
-  int    RCMinQP[5];
-  int    RCMaxQP[5];
+  int    RCMinQP[NUM_SLICE_TYPES];
+  int    RCMaxQP[NUM_SLICE_TYPES];
   int    RCMaxQPChange;
 
   // Search Algorithm
@@ -925,6 +933,7 @@ typedef struct
 
   // Lambda Params
   int UseExplicitLambdaParams;
+  int UpdateLambdaChromaME;
   double LambdaWeight[6];
   double FixedLambda[6];
 
@@ -935,8 +944,8 @@ typedef struct
   int AdaptRoundingFixed;                        //!< Global rounding for all qps
   int AdaptRndPeriod;                            //!< Set period for adaptive rounding of JVT-N011 in MBs
   int AdaptRndChroma;
-  int AdaptRndWFactor[2][5];                     //!< Weighting factors for luma component based on reference indicator and slice type
-  int AdaptRndCrWFactor[2][5];                   //!< Weighting factors for chroma components based on reference indicator and slice type
+  int AdaptRndWFactor  [2][NUM_SLICE_TYPES];     //!< Weighting factors for luma component based on reference indicator and slice type
+  int AdaptRndCrWFactor[2][NUM_SLICE_TYPES];     //!< Weighting factors for chroma components based on reference indicator and slice type
   // Fast Mode Decision
   int EarlySkipEnable;
   int SelectiveIntraEnable;
@@ -954,6 +963,7 @@ typedef struct
   int ChromaMEWeight;
   int MEErrorMetric[3];
   int ModeDecisionMetric;
+  int SkipDeBlockNonRef;
 
   // tone mapping SEI message
   int ToneMappingSEIPresentFlag;
@@ -1047,25 +1057,25 @@ typedef struct
   imgpel mpr_4x4  [MAX_PLANE][9][16][16]; //!< prediction samples for   4x4 intra prediction modes
   imgpel mpr_8x8  [MAX_PLANE][9][16][16]; //!< prediction samples for   8x8 intra prediction modes
   imgpel mpr_16x16[MAX_PLANE][5][16][16]; //!< prediction samples for 16x16 intra prediction modes (and chroma)
-  imgpel mpr      [MAX_PLANE][16][16];    //!< current best prediction mode
-  int    m7       [MAX_PLANE][16][16];    //!< the diff pixel values between the original macroblock/block and its prediction
+  imgpel mb_pred  [MAX_PLANE][16][16];    //!< current best prediction mode
+  int    mb_rres  [MAX_PLANE][16][16];    //!< the diff pixel values between the original macroblock/block and its prediction (reconstructed)
+  int    mb_ores  [MAX_PLANE][16][16];    //!< the diff pixel values between the original macroblock/block and its prediction (original)
 
   int    (*curr_res)[16];                 //!< pointer to current residual
   imgpel (*curr_prd)[16];                 //!< pointer to current prediction
 
   int ****cofAC;               //!< AC coefficients [8x8block][4x4block][level/run][scan_pos]
-  int ***cofDC;                //!< DC coefficients [yuv][level/run][scan_pos]
+  int *** cofDC;               //!< DC coefficients [yuv][level/run][scan_pos]
 
   int ***fadjust4x4;           //!< Transform coefficients for 4x4 luma. Excludes DC for I16x16
   int ***fadjust8x8;           //!< Transform coefficients for 8x8 luma
   int ****fadjust4x4Cr;        //!< Transform coefficients for 4x4 chroma. Excludes DC chroma.
   int ****fadjust8x8Cr;        //!< Transform coefficients for 4x4 chroma within 8x8 inter blocks.
 
-
   Picture       *currentPicture; //!< The coded picture currently in the works (typically p_frame_pic, field_pic[0], or field_pic[1])
   Slice         *currentSlice;                                //!< pointer to current Slice data struct
   Macroblock    *mb_data;                                   //!< array containing all MBs of a whole frame
-
+  Block8x8Info  *b8x8info;                                  //!< block 8x8 information for RDopt
   int *quad;               //!< Array containing square values,used for snr computation  */                                         /* Values are limited to 5000 for pixel differences over 70 (sqr(5000)).
   int *intra_block;
 
@@ -1073,12 +1083,6 @@ typedef struct
   int fld_type;                        //!< top or bottom field
   unsigned int fld_flag;
   unsigned int rd_pass;
-  int direct_intraP_ref[4][4];
-  int pstruct_next_P;
-  int imgtr_next_P_frm;
-  int imgtr_last_P_frm;
-  int imgtr_next_P_fld;
-  int imgtr_last_P_fld;
 
   // B pictures
   double b_interval;
@@ -1089,17 +1093,15 @@ typedef struct
 
   short****** pred_mv;                 //!< motion vector predictors for all block types and all reference frames
   short****** all_mv;                  //!< replaces local all_mv
-
-  short****** bipred_mv1;              //!< Biprediction MVs
-  short****** bipred_mv2;              //!< Biprediction MVs
-  short bi_pred_me[MAXMODE];
-
+  short******* bipred_mv;             //!<Biprediction MVs  
+  
   int DFDisableIdc;
   int DFAlphaC0Offset;
   int DFBetaOffset;
 
   int direct_spatial_mv_pred_flag;              //!< Direct Mode type to be used (0: Temporal, 1: Spatial)
 
+  int num_ref_idx_active_list[2];
   int num_ref_idx_l0_active;
   int num_ref_idx_l1_active;
 
@@ -1110,7 +1112,7 @@ typedef struct
   int i16offset;
 
   int layer;             //!< which layer this picture belonged to
-  int old_layer;         //!< old layer number
+
   int NoResidueDirect;
   int AdaptiveRounding;                          //!< Adaptive Rounding parameter based on JVT-N011
 
@@ -1195,6 +1197,7 @@ typedef struct
   int max_qp_delta;
   int min_qp_delta;
   // Lagrangian Parameters
+  LambdaParams **lambda;
   double  **lambda_md;     //!< Mode decision Lambda
   double ***lambda_me;     //!< Motion Estimation Lambda
   int    ***lambda_mf;     //!< Integer formatted Motion Estimation Lambda
@@ -1203,7 +1206,8 @@ typedef struct
 
   unsigned int dc_pred_value_comp[MAX_PLANE]; //!< component value for DC prediction (depends on component pel bit depth)
   unsigned int dc_pred_value;                 //!< DC prediction value for current component
-  int max_imgpel_value_comp[MAX_PLANE];       //!< max value that one picture element (pixel) can take (depends on pic_unit_bitdepth)
+  int max_imgpel_value_comp      [MAX_PLANE];       //!< max value that one picture element (pixel) can take (depends on pic_unit_bitdepth)
+  int max_imgpel_value_comp_sq   [MAX_PLANE];       //!< max value that one picture element (pixel) can take (depends on pic_unit_bitdepth)
   int max_imgpel_value;              //!< max value that one picture element (pixel) can take (depends on pic_unit_bitdepth)
 
   int num_blk8x8_uv;
@@ -1241,50 +1245,17 @@ typedef struct
   int masterQP;
 } ImageParameters;
 
-#define NUM_PIC_TYPE 5
-                                //!< statistics
-typedef struct
-{
-  int   quant0;                      //!< quant for the first frame
-  int   quant1;                      //!< average quant for the remaining frames
-  float bitr;                        //!< bit rate for current frame, used only for output til terminal
-  float bitrate;                     //!< average bit rate for the sequence except first frame
-  int64 bit_ctr;                     //!< counter for bit usage
-  int64 bit_ctr_n;                   //!< bit usage for the current frame
-  int   bit_slice;                   //!< number of bits in current slice
-  int   stored_bit_slice;            //!< keep number of bits in current slice (to restore status in case of MB re-encoding)
-  int   bit_ctr_emulationprevention; //!< stored bits needed to prevent start code emulation
-  int   b8_mode_0_use[NUM_PIC_TYPE][2];
-  int   mode_use_transform[2][NUM_PIC_TYPE][MAXMODE];
-  int   intra_chroma_mode[4];
 
-  // B pictures
-  int   successive_Bframe;
-  int   *mode_use_Bframe;
-  int   *bit_use_mode_Bframe;
-  int64 bit_ctr_I;
-  int64 bit_ctr_P;
-  int64 bit_ctr_B;
-  float bitrate_I;
-  float bitrate_P;
-  float bitrate_B;
-
-  int64   mode_use            [NUM_PIC_TYPE][MAXMODE]; //!< Macroblock mode usage for Intra frames
-  int64   bit_use_mode        [NUM_PIC_TYPE][MAXMODE]; //!< statistics of bit usage
-  int64   bit_use_stuffingBits[NUM_PIC_TYPE];
-  int64   bit_use_mb_type     [NUM_PIC_TYPE];
-  int64   bit_use_header      [NUM_PIC_TYPE];
-  int64   tmp_bit_use_cbp     [NUM_PIC_TYPE];
-  int64   bit_use_coeffC      [NUM_PIC_TYPE];
-  int64   bit_use_coeff    [3][NUM_PIC_TYPE];  
-  int64   bit_use_delta_quant [NUM_PIC_TYPE];
-
-  int   em_prev_bits_frm;
-  int   em_prev_bits_fld;
-  int  *em_prev_bits;
-  int   bit_ctr_parametersets;
-  int   bit_ctr_parametersets_n;
-} StatParameters;
+//! definition of pic motion parameters
+typedef struct pic_motion_params2
+{
+  int64    ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
+  int64    ref_id;        //!< reference picture identifier [list][subblock_y][subblock_x]
+  short    mv[2];            //!< motion vector       [list][subblock_x][subblock_y][component]
+  char     ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
+  byte     mb_field;      //!< field macroblock indicator
+  byte     field_frame;   //!< indicates if co_located is field or frame.
+} PicMotionParams2;
 
 // Motion Vector structure
 typedef struct
@@ -1320,7 +1291,6 @@ typedef struct
   int    prev_cbp;
   
   int64  cbp_blk;
-  short  bi_pred_me;
   short  ******pred_mv;        //!< predicted motion vectors
   short  ******all_mv;         //!< all modes motion vectors
 
@@ -1346,9 +1316,15 @@ typedef struct
 
 typedef struct
 {
-  int cost8x8;
+  int mb_p8x8_cost;
+  int smb_p8x8_cost[4];
+  double smb_p8x8_rdcost[4]; 
   int lrec[16][16]; // transform and quantized coefficients will be stored here for SP frames
+  int cbp8x8;
+  int cbp_blk8x8;
+  int cnt_nonz_8x8;
   short part8x8mode[4];
+  short part8x8bipred[4];
   char  part8x8pdir[4];
   char  part8x8l0ref[4];
   char  part8x8l1ref[4];
@@ -1356,9 +1332,9 @@ typedef struct
   imgpel mpr8x8[16][16];
   imgpel mpr8x8CbCr[2][16][16];
   imgpel rec_mb8x8_cr[2][16][16];
-
 } RD_8x8DATA;
 
+
 typedef struct
 {
   double lambda_md;        //!< Mode decision Lambda
@@ -1382,12 +1358,10 @@ int   ***motion_cost8;
 
 extern InputParameters *params;
 extern ImageParameters *img;
-extern StatParameters  *stats;
 
-extern SNRParameters *snr;
+extern DistortionParams *dist;
 
 // files
-FILE *p_stat;                    //!< status file for the last encoding session
 FILE *p_log;                     //!< SNR file
 FILE *p_trace;                   //!< Trace file
 int  p_in;                       //!< original YUV file handle
@@ -1404,38 +1378,21 @@ int CbCr_predmode_8x8[4];
  */
 
 void intrapred_4x4   (Macroblock *currMB, ColorPlane pl, int CurrPixX,int CurrPixY, int *left_available, int *up_available, int *all_available);
+void intrapred_16x16 (Macroblock *currMB, ColorPlane pl);
+// Transform function pointers
 int (*pDCT_4x4)      (Macroblock *currMB, ColorPlane pl, int block_x, int block_y, int *coeff_cost, int intra);
 int (*pDCT_16x16)    (Macroblock *currMB, ColorPlane pl, int);
 int (*pDCT_8x8)      (Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra);
-int  dct_4x4         (Macroblock *currMB, ColorPlane pl, int pos_mb1, int pos_mb2, int *cnt_nonz, int intra);
-int  dct_4x4_ls      (Macroblock *currMB, ColorPlane pl, int block_x, int block_y, int *coeff_cost, int intra);
-int  dct_16x16       (Macroblock *currMB, ColorPlane pl, int);
-int  dct_16x16_ls    (Macroblock *currMB, ColorPlane pl, int);
+int  (*dct_cr_4x4[2])   (Macroblock *currMB, int uv,int i11);
+
 int  dct_8x8         (Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra);
 int  dct_8x8_cavlc   (Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra);
 int  dct_8x8_ls      (Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra);
 
-
-int  dct_4x4_sp      (Macroblock *currMB, ColorPlane pl, int pos_mb1,int pos_mb2,int *cnt_nonz, int intra);
-int  dct_4x4_sp2     (Macroblock *currMB, ColorPlane pl, int pos_mb1,int pos_mb2,int *cnt_nonz, int intra);
 void copyblock_sp    (Macroblock *currMB, ColorPlane pl, int pos_mb1,int pos_mb2);
-int  (*dct_cr_4x4[2])   (Macroblock *currMB, int uv,int i11);
-int  dct_chroma      (Macroblock *currMB, int uv,int i11);
 int  dct_chroma_sp   (Macroblock *currMB, int uv,int i11);
 int  dct_chroma_sp2  (Macroblock *currMB, int uv,int i11);
 
-//For residual DPCM
-int Residual_DPCM_4x4(int ipmode, int m7[16][16], int block_y, int block_x);  
-
-
-void intrapred_16x16 (Macroblock *currMB, ColorPlane pl);
-
-void init_poc(void);
-
-void init_img(void);
-void report(void);
-int  get_picture_type(void);
-void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***) ;
 
 int  distortion4x4(int*);
 int  distortion8x8(int*);
@@ -1444,34 +1401,28 @@ extern int*   refbits;
 extern int**** motion_cost;
 double *mb16x16_cost_frame;
 
+void  FindSkipModeMotionVector  (Macroblock *currMB);
 void  Get_Direct_Motion_Vectors (Macroblock *currMB);
 void  PartitionMotionSearch     (Macroblock *currMB, int, int, int*);
 int   BIDPartitionCost          (Macroblock *currMB, int, int, char[2], int);
-int   writeAbpCoeffIndex        (int, int, int, int);
+int   BPredPartitionCost        (Macroblock *currMB, int, int, short, short, int, int);
+int   GetDirectCostMB           (Macroblock *currMB, int bslice);
+int   GetDirectCost8x8          (Macroblock *currMB, int, int*);
 
 
-void poc_based_ref_management(int current_pic_num);
+void poc_based_ref_management_frame_pic(int current_pic_num);
+void poc_based_ref_management_field_pic(int current_pic_num);
+
 int  picture_coding_decision (Picture *picture1, Picture *picture2, int qp);
 
 unsigned CeilLog2( unsigned uiVal);
 
-int  GetDirectCost8x8 (Macroblock *currMB, int, int*);
-
-int  BPredPartitionCost (Macroblock *currMB, int, int, short, short, int, int);
-
-int  GetDirectCostMB  (Macroblock *currMB, int bslice);
-
-int  GetSkipCostMB (Macroblock *currMB);
-void FindSkipModeMotionVector (Macroblock *currMB);
-
 
 // dynamic mem allocation
 int  init_global_buffers(void);
 void free_global_buffers(void);
 void no_mem_exit  (char *where);
 
-int  get_mem_mv  (short*******);
-void free_mem_mv (short******);
 void free_img    (void);
 
 int  get_mem_ACcoeff  (int*****);
@@ -1482,62 +1433,23 @@ void free_mem_DCcoeff (int***);
 int  decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bit_frame, double lambda_picture);
 void combine_field(void);
 
-Picture *malloc_picture(void);
-void     free_picture (Picture *pic);
-
 int   encode_one_slice(int SLiceGroupId, Picture *pic, int TotalCodedMBs);   //! returns the number of MBs in the slice
 
-
-void  trellis_coding(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb);
-
 void free_slice_list(Picture *currPic);
 
-void report_stats_on_error(void);
-
 #if TRACE
 void  trace2out(SyntaxElement *se);
 void  trace2out_cabac(SyntaxElement *se);
 #endif
 
-
 void error(char *text, int code);
-int  start_sequence(void);
-int  rewrite_paramsets(void);
-int  terminate_sequence(void);
-int  start_slice(void);
-int  terminate_slice(int);
-int  write_PPS(int, int);
-
-// B pictures
-void InitMotionVectorSearchModule(void);
 
 int  field_flag_inference(Macroblock  *currMB);
-
 void set_mbaff_parameters(Macroblock  *currMB);  // For MB AFF
-void writeVlcByteAlign(Bitstream* currStream);
-
-//============= rate-distortion optimization ===================
-void  clear_rdopt      (void);
-void  init_rdopt       (void);
-//============= rate-distortion opt with packet losses ===========
-void decode_one_macroblock(void);
-void decode_one_mb (int, Macroblock*);
-void decode_one_b8block (int, int, int, short, short);
-
-void compute_residue_b8block (int, int);
-void compute_residue_mb (int);
-void UpdateDecoders(void);
 
 //============= restriction of reference frames based on the latest intra-refreshes==========
 void UpdatePixelMap(void);
 
-//============= fast full integer search =======================
-void  ClearFastFullIntegerSearch    (void);
-void  ResetFastFullIntegerSearch    (void);
-
-void SetImgType(void);
-
-
 int64 compute_SSE(imgpel **imgRef, imgpel **imgSrc, int xRef, int xSrc, int ySize, int xSize);
 
 // Tian Dong: for IGOPs
@@ -1553,33 +1465,32 @@ int CalculateFrameNumber(void);
 
 void AllocNalPayloadBuffer(void);
 void FreeNalPayloadBuffer(void);
-void SODBtoRBSP(Bitstream *currStream);
-int RBSPtoEBSP(byte *streamBuffer, int begin_bytepos, int end_bytepos, int min_num_bytes);
-int Bytes_After_Header;
-
-void reset_valid_modes(RD_PARAMS *enc_mb);
+void SODBtoRBSP (Bitstream *currStream);
+int  RBSPtoEBSP (byte *streamBuffer, int begin_bytepos, int end_bytepos, int min_num_bytes);
+int  Bytes_After_Header;
 
-// Fast ME enable
-int BlockMotionSearch (Macroblock *currMB, short,int,int,int,int,int, int*);
-void low_complexity_encode_md (void);
 void encode_one_macroblock_low (Macroblock *currMB);
 void encode_one_macroblock_high (Macroblock *currMB);
 void encode_one_macroblock_highfast (Macroblock *currMB);
 void encode_one_macroblock_highloss (Macroblock *currMB);
 void (*encode_one_macroblock) (Macroblock *currMB);
 
-void update_qp    (Macroblock *currMB);
+int is_bipred_enabled(int mode); 
+
+void update_qp    (ImageParameters *img, Macroblock *currMB);
 void select_plane (ColorPlane color_plane);
-void select_dct   (Macroblock *currMB);
+void select_dct   (ImageParameters *img, Macroblock *currMB);
 
 void store_coding_state_cs_cm(Macroblock *currMB);
 void reset_coding_state_cs_cm(Macroblock *currMB);
 
-int writeIPCMBytes(Bitstream *currStream);
+int writeIPCMBytes   (Bitstream *currStream);
 int writePCMByteAlign(Bitstream *currStream);
 
 void set_slice_type(int slice_type);
 
+void free_encoder_memory(ImageParameters *img);
+
 int check_for_SI16(void);
 int **lrec ;
 int ***lrec_uv;
@@ -1587,8 +1498,7 @@ int si_frame_indicator;
 
 int sp2_frame_indicator;
 int number_sp2_frames;
-//#define sp_output_indicator 0 //will be in the config file
-//#define sp_output_filename "sp_stored.txt" // will be in the config file
+
 void output_SP_coefficients(void);
 void read_SP_coefficients(void);
 
@@ -1601,10 +1511,10 @@ int gaaiMBAFF_NZCoeff[4][12];
 // Redundant picture
 imgpel **imgY_tmp;
 imgpel **imgUV_tmp[2];
-int frameNuminGOP;
-int redundant_coding;
-int key_frame;
-int redundant_ref_idx;
+int  frameNuminGOP;
+int  redundant_coding;
+int  key_frame;
+int  redundant_ref_idx;
 void Init_redundant_frame(void);
 void Set_redundant_frame(void);
 void encode_one_redundant_frame(void);
@@ -1628,8 +1538,9 @@ int img_cr_padded_size_x2;
 int img_cr_padded_size_x4;
 
 // struct with pointers to the sub-images
-typedef struct {
-  imgpel ****luma; // component 0 (usually Y, X, or R)
+typedef struct 
+{
+  imgpel ****luma;    // component 0 (usually Y, X, or R)
   imgpel ****crcb[2]; // component 2 (usually U/V, Y/Z, or G/B)
 } SubImageContainer;
 
diff --git a/lencod/inc/ifunctions.h b/lencod/inc/ifunctions.h
index f552278..157600e 100644
--- a/lencod/inc/ifunctions.h
+++ b/lencod/inc/ifunctions.h
@@ -21,6 +21,7 @@
   #define static
   #define inline
 #endif
+#include <math.h>
 
 static inline int imin(int a, int b)
 {
@@ -97,6 +98,11 @@ static inline int rshift_rnd(int x, int a)
   return (a > 0) ? ((x + (1 << (a-1) )) >> a) : (x << (-a));
 }
 
+static inline int rshift_rnd_sign(int x, int a)
+{
+  return (x > 0) ? ( ( x + (1 << (a-1)) ) >> a ) : (-( ( iabs(x) + (1 << (a-1)) ) >> a ));
+}
+
 static inline unsigned int rshift_rnd_us(unsigned int x, unsigned int a)
 {
   return (a > 0) ? ((x + (1 << (a-1))) >> a) : x;
@@ -156,6 +162,19 @@ static inline int float2int (float x)
   return (int)((x < 0) ? (x - 0.5f) : (x + 0.5f));
 }
 
+#if ZEROSNR
+static inline float psnr(int max_sample_sq, int samples, float sse_distortion ) 
+{
+  return (float) (10.0 * log10(max_sample_sq * (double) ((double) samples / (sse_distortion == 0.0 ? 1.0 : sse_distortion))));
+}
+#else
+static inline float psnr(int max_sample_sq, int samples, float sse_distortion ) 
+{
+  return (float) (sse_distortion == 0.0 ? 0.0 : (10.0 * log10(max_sample_sq * (double) ((double) samples / sse_distortion))));
+}
+#endif
+
+
 # if !defined(WIN32) && (__STDC_VERSION__ < 199901L)
   #undef static
   #undef inline
diff --git a/lencod/inc/image.h b/lencod/inc/image.h
index 389f939..94e909f 100644
--- a/lencod/inc/image.h
+++ b/lencod/inc/image.h
@@ -7,8 +7,11 @@
  *    headers for image processing
  *
  * \author
- *  Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
- *  Copyright (C) 1999  Telenor Satellite Services, Norway
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Karsten Sühring                 <suehring@hhi.de> 
+ *     - Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
+ *  
  ************************************************************************
  */
 #ifndef _IMAGE_H_
@@ -21,14 +24,14 @@ extern StorablePicture **enc_frame_picture;
 extern StorablePicture **enc_field_picture;
 extern StorablePicture *enc_frame_picture_JV[MAX_PLANE];  //!< enc_frame to be used during 4:4:4 independent mode encoding
 
-int encode_one_frame (void);
-void report_frame_statistic(void);
+int  encode_one_frame (void);
 Boolean dummy_slice_too_big(int bits_slice);
 void copy_rdopt_data (Macroblock *currMB, int field_type);       // For MB level field/frame coding tools
 
 void UnifiedOneForthPix (StorablePicture *s);
 // For 4:4:4 independent mode
 void UnifiedOneForthPix_JV (int nplane, StorablePicture *s);
+void frame_picture (Picture *frame, int rd_pass);
 
 
 #endif
diff --git a/lencod/inc/img_dist_ms_ssim.h b/lencod/inc/img_dist_ms_ssim.h
new file mode 100644
index 0000000..19c5918
--- /dev/null
+++ b/lencod/inc/img_dist_ms_ssim.h
@@ -0,0 +1,25 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    img_dist_ms_ssim.h
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *
+ * \date
+ *    18 July 2008
+ *
+ * \brief
+ *    Headerfile to calculate multi-scale structural similarity (SSIM) index
+ **************************************************************************
+ */
+
+#ifndef _IMG_DIST_MS_SSIM_H_
+#define _IMG_DIST_MS_SSIM_H_
+#include "img_distortion.h"
+
+void find_ms_ssim (ImageStructure *imgREF, ImageStructure *imgSRC, DistMetric metricMS_SSIM[3]);
+
+#endif
diff --git a/lencod/inc/img_dist_snr.h b/lencod/inc/img_dist_snr.h
new file mode 100644
index 0000000..08d8edc
--- /dev/null
+++ b/lencod/inc/img_dist_snr.h
@@ -0,0 +1,24 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    img_dist_snr.h
+ *
+ * \author
+ *    Woo-Shik Kim
+ *
+ * \date
+ *    29 May 2008
+ *
+ * \brief
+ *    Headerfile to calculate signal to noise ratio (SNR)
+ **************************************************************************
+ */
+
+#ifndef _IMG_DIST_SNR_H_
+#define _IMG_DIST_SNR_H_
+#include "img_distortion.h"
+
+void find_snr(ImageStructure *imgREF, ImageStructure *imgSRC, DistMetric metricSSE[3], DistMetric metricPSNR[3]);
+
+#endif
+
diff --git a/lencod/inc/img_dist_ssim.h b/lencod/inc/img_dist_ssim.h
new file mode 100644
index 0000000..c10b278
--- /dev/null
+++ b/lencod/inc/img_dist_ssim.h
@@ -0,0 +1,26 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    img_dist_ssim.h
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *
+ * \date
+ *    29 May 2008
+ *
+ * \brief
+ *    Headerfile to calculate structural similarity (SSIM) index
+ **************************************************************************
+ */
+
+#ifndef _IMG_DIST_SSIM_H_
+#define _IMG_DIST_SSIM_H_
+#include "img_distortion.h"
+
+void find_ssim (ImageStructure *imgREF, ImageStructure *imgSRC, DistMetric metricSSIM[3]);
+
+#endif
+
diff --git a/lencod/inc/img_distortion.h b/lencod/inc/img_distortion.h
new file mode 100644
index 0000000..e1479be
--- /dev/null
+++ b/lencod/inc/img_distortion.h
@@ -0,0 +1,33 @@
+
+/*!
+ ************************************************************************
+ * \file img_distortion.h
+ *
+ * \brief
+ *    Distortion related definitions
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *
+ ************************************************************************
+ */
+
+#ifndef _IMG_DISTORTION_H_
+#define _IMG_DISTORTION_H_
+
+typedef struct
+{  
+  FrameFormat format;      //!< ImageStructure format Information
+  imgpel **data[3];        //!< ImageStructure pixel data
+} ImageStructure;
+
+void accumulate_avslice(DistMetric metric[3], int slice_type, int frames);
+void accumulate_average(DistMetric metric[3], int frames);
+void find_distortion(void);
+void select_img(ImageStructure *imgSRC, ImageStructure *imgREF);
+void compute_distortion(void);
+
+#endif
+
diff --git a/lencod/inc/macroblock.h b/lencod/inc/macroblock.h
index 60ee121..357bcfc 100644
--- a/lencod/inc/macroblock.h
+++ b/lencod/inc/macroblock.h
@@ -41,7 +41,7 @@ int  writeMBLayer (Macroblock *currMB, int rdopt, int *coeff_rate);
 void write_terminating_bit (short bit);
 
 int  writeReferenceFrame  (Macroblock *currMB, int mode, int i, int j, int fwd_flag, int  ref);
-int  writeMotionVector8x8 (Macroblock *currMB, int  i0, int  j0, int  i1, int  j1, int  refframe, int  list_idx, int  mv_mode);
+int  writeMotionVector8x8 (Macroblock *currMB, int  i0, int  j0, int  i1, int  j1, int  refframe, int  list_idx, int  mv_mode, short bipred_me);
 
 int  writeCoeff4x4_CABAC (Macroblock *currMB, ColorPlane, int, int, int);
 int  writeCoeff8x8_CABAC (Macroblock* currMB, ColorPlane, int, int);
@@ -57,7 +57,10 @@ int distortion_hadamard(imgpel **img_org, imgpel pred_img[16][16]);
 double (*find_sad_16x16) (Macroblock *currMB, int *intra_mode);
 double find_sad_16x16_JM (Macroblock *currMB, int *intra_mode);
 
-void SetLagrangianMultipliers();
+void SetLagrangianMultipliersOn();
+void SetLagrangianMultipliersOff();
+void (*SetLagrangianMultipliers)();
+
 void  init_slice(int start_mb_addr);
 
 #endif
diff --git a/lencod/inc/mb_access.h b/lencod/inc/mb_access.h
index 80f56a3..3a86eb4 100644
--- a/lencod/inc/mb_access.h
+++ b/lencod/inc/mb_access.h
@@ -8,7 +8,8 @@
  *
  * \author
  *     Main contributors (see contributors.h for copyright, address and affiliation details)
- *     - Karsten Sühring          <suehring@hhi.de>
+ *     - Karsten Sühring                 <suehring@hhi.de> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>  
  *************************************************************************************
  */
 
diff --git a/lencod/inc/mbuffer.h b/lencod/inc/mbuffer.h
index f5c8aad..bdfe8ab 100644
--- a/lencod/inc/mbuffer.h
+++ b/lencod/inc/mbuffer.h
@@ -24,6 +24,18 @@ typedef struct picture_stats
 } PictureStats;
 
 
+//! definition of pic motion parameters
+typedef struct pic_motion_params
+{
+  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
+  int64 ***   ref_id;        //!< reference picture identifier [list][subblock_y][subblock_x]
+  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
+  byte *      mb_field;      //!< field macroblock indicator
+  byte **     field_frame;   //!< indicates if co_located is field or frame.
+
+} PicMotionParams;
+
 //! definition a picture (field or frame)
 typedef struct storable_picture
 {
@@ -58,28 +70,26 @@ typedef struct storable_picture
 
   imgpel **   imgY;          //!< Y picture component
   imgpel **** imgY_sub;      //!< Y picture component upsampled (Quarter pel)
-  imgpel *****imgUV_sub;     //!< UV picture component upsampled (Quarter/One-Eighth pel)
   imgpel ***  imgUV;         //!< U and V picture components
+  imgpel *****imgUV_sub;     //!< UV picture component upsampled (Quarter/One-Eighth pel)
+
+  //Multiple Decoder Buffers (used if rdopt==3)
+  imgpel ***  dec_imgY;       //!< Decoded Y component in multiple hypothetical decoders
+  imgpel **** dec_imgUV;      //!< Decoded U and V components in multiple hypothetical decoders
+  imgpel ***  p_dec_img[MAX_PLANE];      //!< pointer array for accessing decoded pictures in hypothetical decoders
+
+  byte   ***  mb_error_map;    //!< Map of macroblock errors in hypothetical decoders.
 
   imgpel **   p_img[MAX_PLANE];          //!< pointer array for accessing imgY/imgUV[]
   imgpel **** p_img_sub[MAX_PLANE];      //!< pointer array for storing top address of imgY_sub/imgUV_sub[]
   imgpel **   p_curr_img;                //!< current int-pel ref. picture area to be used for motion estimation
   imgpel **** p_curr_img_sub;            //!< current sub-pel ref. picture area to be used for motion estimation
 
-  byte *      mb_field;      //!< field macroblock indicator
-
-  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-
-  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-                             //   (not  simply index)
-
-  int64 ***   ref_id;        //!< reference picture identifier [list][subblock_y][subblock_x]
-                             //   (not  simply index)
-
-  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  PicMotionParams2 ***mv_info;    //!< Motion info
+  PicMotionParams  motion;    //!< Motion info
+  PicMotionParams JVmotion[MAX_PLANE];    //!< Motion info for 4:4:4 independent coding
 
-  byte **     moving_block;
-  byte **     field_frame;         //!< indicates if co_located is field or frame.
+  int colour_plane_id;                     //!< colour_plane_id to be used for 4:4:4 independent mode encoding
 
   struct storable_picture *top_field;     // for mb aff, if frame for referencing the top field
   struct storable_picture *bottom_field;  // for mb aff, if frame for referencing the bottom field
@@ -93,46 +103,30 @@ typedef struct storable_picture
   int         frame_cropping_rect_top_offset;
   int         frame_cropping_rect_bottom_offset;
 
-  char  ***   ref_idx_JV[MAX_PLANE];       //!< ref_idx to be used for 4:4:4 independent mode encoding
-  int64 ***   ref_pic_id_JV[MAX_PLANE];    //!< ref_pic_id to be used for 4:4:4 independent mode encoding
-  int64 ***   ref_id_JV[MAX_PLANE];        //!< ref_id to be used for 4:4:4 independent mode encoding
-  short ****  mv_JV[MAX_PLANE];            //!< mv to be used for 4:4:4 independent mode encoding
-  int colour_plane_id;                     //!< colour_plane_id to be used for 4:4:4 independent mode encoding
 
   PictureStats p_stats;
   
 } StorablePicture;
 
+//! definition of motion parameters
+typedef struct motion_params
+{
+  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
+  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
+  byte **     moving_block;
+} MotionParams;
 
 //! definition a picture (field or frame)
 typedef struct colocated_params
 {
   int         mb_adaptive_frame_field_flag;
   int         size_x, size_y;
-
-  int64       ref_pic_num[6][MAX_LIST_SIZE];
-
-  char  ***   ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
-  byte **     moving_block;
-
-  // Top field params
-  int64       top_ref_pic_num[6][MAX_LIST_SIZE];
-  char  ***   top_ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   top_ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  top_mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
-  byte **     top_moving_block;
-
-  // Bottom field params
-  int64       bottom_ref_pic_num[6][MAX_LIST_SIZE];
-  char  ***   bottom_ref_idx;       //!< reference picture   [list][subblock_y][subblock_x]
-  int64 ***   bottom_ref_pic_id;    //!< reference picture identifier [list][subblock_y][subblock_x]
-  short ****  bottom_mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
-  byte **     bottom_moving_block;
-
   byte        is_long_term;
-  byte **     field_frame;         //!< indicates if co_located is field or frame.
+
+  MotionParams frame;
+  MotionParams top;
+  MotionParams bottom;
 
 } ColocatedParams;
 
diff --git a/lencod/inc/mc_prediction.h b/lencod/inc/mc_prediction.h
index 0a76fc5..9ef0fba 100644
--- a/lencod/inc/mc_prediction.h
+++ b/lencod/inc/mc_prediction.h
@@ -16,10 +16,10 @@
 #define _MC_PREDICTION_H_
 #include "mbuffer.h"
 
-void LumaPrediction      ( Macroblock* currMB, int, int, int, int, int, int, int, short, short );
+void LumaPrediction      ( Macroblock* currMB, int, int, int, int, int, int, int, short, short, short );
 void LumaPredictionBi    ( Macroblock* currMB, int, int, int, int, int, int, short, short, int );
-void ChromaPrediction    ( Macroblock* currMB, int, int, int, int, int, int, int, int, short, short );
-void ChromaPrediction4x4 ( Macroblock* currMB, int, int, int, int, int, int, short, short);   
+void ChromaPrediction    ( Macroblock* currMB, int, int, int, int, int, int, int, int, short, short, short );
+void ChromaPrediction4x4 ( Macroblock* currMB, int, int, int, int, int, int, short, short, short);   
 
 // function pointer for different ways of obtaining chroma interpolation
 void (*OneComponentChromaPrediction4x4)         (imgpel* , int , int , short*** , StorablePicture *listX, int );
@@ -29,7 +29,7 @@ void OneComponentChromaPrediction4x4_retrieve   (imgpel* , int , int , short***
 void IntraChromaPrediction ( Macroblock *currMB, int*, int*, int*);
 void IntraChromaRDDecision ( Macroblock *currMB, RD_PARAMS);
 
-void ComputeResidue (imgpel **curImg, imgpel mpr[16][16], int img_m7[16][16], int mb_y, int mb_x, int opix_y, int opix_x, int width, int height);
-void SampleReconstruct (imgpel **curImg, imgpel mpr[16][16], int img_m7[16][16], int mb_y, int mb_x, int opix_y, int opix_x, int width, int height, int max_imgpel_value, int dq_bits);
+void ComputeResidue    (imgpel **curImg, imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE], int img_m7[MB_BLOCK_SIZE][MB_BLOCK_SIZE], int mb_y, int mb_x, int opix_y, int opix_x, int width, int height);
+void SampleReconstruct (imgpel **curImg, imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE], int img_m7[MB_BLOCK_SIZE][MB_BLOCK_SIZE], int mb_y, int mb_x, int opix_y, int opix_x, int width, int height, int max_imgpel_value, int dq_bits);
 #endif
 
diff --git a/lencod/inc/me_epzs.h b/lencod/inc/me_epzs.h
index 1a7bbb2..ba792f1 100644
--- a/lencod/inc/me_epzs.h
+++ b/lencod/inc/me_epzs.h
@@ -27,14 +27,13 @@ typedef struct
 {
   int         mb_adaptive_frame_field_flag;
   int         size_x, size_y;
-
+  
   // Frame
-  short ****  mv;            //!< motion vector       [list][subblock_x][subblock_y][component]
+  MotionVector ***frame;  //!< motion vector       [list][subblock_x][subblock_y]
   // Top field
-  short ****  top_mv;        //!< motion vector       [list][subblock_x][subblock_y][component]
-  // Bottom field params
-  short ****  bottom_mv;     //!< motion vector       [list][subblock_x][subblock_y][component]
-
+  MotionVector ***top;    //!< motion vector       [list][subblock_x][subblock_y]
+  // Bottom field
+  MotionVector ***bot;    //!< motion vector       [list][subblock_x][subblock_y]
 } EPZSColocParams;
 
 typedef struct
@@ -67,16 +66,16 @@ typedef enum
 extern EPZSColocParams *EPZSCo_located;
 extern int ***EPZSDistortion;  //!< Array for storing SAD Values
 
-extern int  EPZSInit(void);
-extern void EPZSDelete (void);
-extern void EPZSOutputStats(FILE *stat,short stats_file);
-extern void EPZSSliceInit(EPZSColocParams* p, StorablePicture **listX[6]);
+extern int  EPZSInit        (InputParameters *params, ImageParameters *img);
+extern void EPZSDelete      (InputParameters *params);
+extern void EPZSOutputStats (InputParameters *params, FILE * stat, short stats_file);
+extern void EPZSSliceInit   (InputParameters *params, ImageParameters *img, EPZSColocParams* p, StorablePicture **listX[6]);
 extern int  EPZSPelBlockMotionSearch (Macroblock *, imgpel *, short, int, int, char ***, short ****,
                                      int, int, int, short[2], short[2], int, int, int, int);
 
 extern int  EPZSBiPredBlockMotionSearch (Macroblock *, imgpel *, short, int, int, char  ***, short  ****,
                                         int, int, int, short[2], short[2],
-                                        short[2], short[2], int, int, int, int);
+                                        short[2], short[2], int, int, int, int, int);
 
 extern int EPZSSubPelBlockMotionSearch (imgpel *, short, int, int, int, int, int, short[2],
                                         short[2], int, int, int, int*, int);
diff --git a/lencod/inc/me_fullfast.h b/lencod/inc/me_fullfast.h
index 98931b5..a1d7c3b 100644
--- a/lencod/inc/me_fullfast.h
+++ b/lencod/inc/me_fullfast.h
@@ -21,9 +21,9 @@
 int FastFullPelBlockMotionSearch (Macroblock *currMB, imgpel* orig_pic, short ref, int list, int list_offset, 
                                   char ***refPic, short ****tmp_mv, int pic_pix_x, int pic_pix_y, int blocktype, short pred_mv[2], short mv[2],
                               int search_range,  int min_mcost, int lambda_factor, int apply_weights);
-void InitializeFastFullIntegerSearch ();
-void ResetFastFullIntegerSearch ();
-void ClearFastFullIntegerSearch ();
+void InitializeFastFullIntegerSearch (void);
+void ResetFastFullIntegerSearch (void);
+void ClearFastFullIntegerSearch (void);
 
 #endif
 
diff --git a/lencod/inc/me_fullsearch.h b/lencod/inc/me_fullsearch.h
index 05783b6..ddee7c8 100644
--- a/lencod/inc/me_fullsearch.h
+++ b/lencod/inc/me_fullsearch.h
@@ -25,7 +25,7 @@ extern int FullPelBlockMotionSearch (Macroblock *currMB, imgpel* orig_pic, short
 extern int FullPelBlockMotionBiPred (Macroblock *currMB, imgpel* orig_pic, short ref, int list, int list_offset, 
                                      char ***refPic, short ****tmp_mv, int pic_pix_x, int pic_pix_y,
                                      int blocktype, short pred_mv1[2], short pred_mv2[2], short mv1[2], short mv2[2],
-                                     int search_range, int min_mcost, int lambda_factor, int apply_weights);
+                                     int search_range, int min_mcost, int iteration_no, int lambda_factor, int apply_weights);
 extern int SubPelBlockMotionSearch  (imgpel* orig_pic, short ref, int list, int list_offset, int pic_pix_x, int pic_pix_y,
                                      int blocktype, short pred_mv[2], short mv[2],
                                      int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);
diff --git a/lencod/inc/me_umhex.h b/lencod/inc/me_umhex.h
index 8734344..6934724 100644
--- a/lencod/inc/me_umhex.h
+++ b/lencod/inc/me_umhex.h
@@ -200,6 +200,7 @@ UMHEXBipredIntegerPelBlockMotionSearch (Macroblock *currMB, // <--  current Macr
                                        short     s_mv[2],       // <--> in: search center (x) / out: motion vector (x) - in pel units
                                        int       search_range,  // <--  1-d search range in pel units
                                        int       min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                                       int       iteration_no,  // <--  bi pred iteration number
                                        int       lambda_factor, // <--  lagrangian parameter for determining motion cost
                                        int       apply_weights
                                        );
diff --git a/lencod/inc/me_umhexsmp.h b/lencod/inc/me_umhexsmp.h
index e009f42..0b26b61 100644
--- a/lencod/inc/me_umhexsmp.h
+++ b/lencod/inc/me_umhexsmp.h
@@ -121,6 +121,7 @@ smpUMHEXBipredIntegerPelBlockMotionSearch (Macroblock *currMB,      // <--  curr
                                            short     s_mv[2],       // <--> in: search center (x|y) / out: motion vector (x|y) - in pel units
                                            int       search_range,  // <--  1-d search range in pel units
                                            int       min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                                           int       iteration_no,  // <--  bi pred iteration number
                                            int       lambda_factor, // <--  lagrangian parameter for determining motion cost
                                            int       apply_weights
                                            );
diff --git a/lencod/inc/memalloc.h b/lencod/inc/memalloc.h
index b31ebf1..9de23ef 100644
--- a/lencod/inc/memalloc.h
+++ b/lencod/inc/memalloc.h
@@ -8,12 +8,26 @@
  *
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Karsten Sühring                 <suehring@hhi.de> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
+ *
  ************************************************************************
  */
 
 #ifndef _MEMALLOC_H_
 #define _MEMALLOC_H_
 
+int  get_mem2Dlm (LambdaParams ***array2D, int dim0, int dim1);
+int  get_mem2Dolm(LambdaParams ***array2D, int dim0, int dim1, int offset);
+
+int  get_mem2Dmp(PicMotionParams2 ***array2D, int dim0, int dim1);
+int  get_mem3Dmp(PicMotionParams2 ****array3D, int dim0, int dim1, int dim2);
+
+int  get_mem2Dmv(MotionVector ***array2D, int dim0, int dim1);
+int  get_mem3Dmv(MotionVector ****array3D, int dim0, int dim1, int dim2);
+int  get_mem4Dmv(MotionVector *****array4D, int dim0, int dim1, int dim2, int dim3);
+int  get_mem5Dmv(MotionVector ******array5D, int dim0, int dim1, int dim2, int dim3, int dim4);
+
 int  get_mem2D(byte ***array2D, int rows, int columns);
 int  get_mem3D(byte ****array2D, int frames, int rows, int columns);
 
@@ -32,21 +46,33 @@ int  get_mem5Dshort(short ******array5D, int dim0, int dim1, int dim2, int dim3,
 int  get_mem6Dshort(short *******array6D, int dim0, int dim1, int dim2, int dim3, int dim4, int dim5);
 int  get_mem7Dshort(short ********array7D, int dim0, int dim1, int dim2, int dim3, int dim4, int dim5, int dim6);
 
-int get_mem2Dpel(imgpel ***array2D, int rows, int columns);
-int get_mem3Dpel(imgpel ****array3D, int frames, int rows, int columns);
-int get_mem4Dpel(imgpel *****array4D, int sub_x, int sub_y, int rows, int columns);
-int get_mem5Dpel(imgpel ******array5D, int dims, int sub_x, int sub_y, int rows, int columns);
+int  get_mem2Dpel(imgpel ***array2D, int rows, int columns);
+int  get_mem3Dpel(imgpel ****array3D, int frames, int rows, int columns);
+int  get_mem4Dpel(imgpel *****array4D, int sub_x, int sub_y, int rows, int columns);
+int  get_mem5Dpel(imgpel ******array5D, int dims, int sub_x, int sub_y, int rows, int columns);
+
+int  get_mem2Ddouble (double ***array2D, int rows, int columns);
+int  get_mem2Dodouble(double ***array2D, int rows, int columns, int offset);
+int  get_mem3Dodouble(double ****array2D, int rows, int columns, int pels, int offset);
 
-int get_mem2Ddouble(double ***array2D, int rows, int columns);
-int get_mem2Ddb_offset(double ***array2D, int rows, int columns, int offset);
-int get_mem3Ddb_offset(double ****array2D, int rows, int columns, int pels, int offset);
+int  get_mem2Doint (int ***array2D, int rows, int columns, int offset);
+int  get_mem3Doint (int ****array3D, int rows, int columns, int pels, int offset);
 
-int get_mem2Dint_offset(int ***array2D, int rows, int columns, int offset);
-int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int offset);
+int  get_offset_mem2Dshort(short ***array2D, int rows, int columns, int offset_y, int offset_x);
 
-int get_offset_mem2Dshort(short ***array2D, int rows, int columns, int offset_y, int offset_x);
 void free_offset_mem2Dshort(short **array2D, int columns, int offset_x, int offset_y);
 
+void free_mem2Dlm   (LambdaParams **array2D);
+void free_mem2Dolm  (LambdaParams **array2D, int offset);
+
+void free_mem2Dmp   (PicMotionParams2    **array2D);
+void free_mem3Dmp   (PicMotionParams2   ***array2D);
+
+void free_mem2Dmv   (MotionVector    **array2D);
+void free_mem3Dmv   (MotionVector   ***array2D);
+void free_mem4Dmv   (MotionVector  ****array2D);
+void free_mem5Dmv   (MotionVector *****array2D);
+
 void free_mem2D     (byte      **array2D);
 void free_mem3D     (byte     ***array2D);
 
@@ -71,10 +97,11 @@ void free_mem4Dpel  (imgpel  ****array4D);
 void free_mem5Dpel  (imgpel *****array5D);
 
 void free_mem2Ddouble(double **array2D);
-void free_mem2Ddb_offset(double **array2D, int offset);
-void free_mem2Dint_offset(int **array2D, int offset);
-void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset);
-void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset);
+
+void free_mem2Dodouble(double **array2D, int offset);
+void free_mem3Dodouble(double ***array3D, int rows, int columns, int offset);
+void free_mem2Doint   (int **array2D, int offset);
+void free_mem3Doint   (int ***array3D, int rows, int columns, int offset);
 
 int init_top_bot_planes(imgpel **imgFrame, int rows, int columns, imgpel ***imgTopField, imgpel ***imgBotField);
 void free_top_bot_planes(imgpel **imgTopField, imgpel **imgBotField);
diff --git a/lencod/inc/mode_decision.h b/lencod/inc/mode_decision.h
index 452864e..42cedba 100644
--- a/lencod/inc/mode_decision.h
+++ b/lencod/inc/mode_decision.h
@@ -4,7 +4,8 @@
  *    mode_decision.h
  *
  * \author
- *    Alexis Michael Tourapis
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
  *
  * \date
  *    21. February 2005
@@ -34,18 +35,11 @@ extern int    cbp, cbp8x8, cnt_nonz_8x8;
 extern int64  cbp_blk8_8x8ts;
 extern int    cbp8_8x8ts;
 extern int    cnt_nonz8_8x8ts;
-extern int    qp_mbaff[2][2], qp_mbaff[2][2];
-extern int    delta_qp_mbaff[2][2],delta_qp_mbaff[2][2];
 
 // Residue Color Transform
 extern char   b4_ipredmode[16], b4_intra_pred_modes[16];
 
-extern short  bi_pred_me;
 extern short  best_mode;
-extern short  best8x8mode          [4]; // [block]
-extern char   best8x8pdir [MAXMODE][4]; // [mode][block]
-extern char   best8x8l0ref[MAXMODE][4]; // [mode][block]
-extern char   best8x8l1ref[MAXMODE][4]; // [mode][block]
 extern imgpel pred[16][16];
 
 extern void   set_stored_macroblock_parameters (Macroblock *currMB);
@@ -53,9 +47,12 @@ extern void   StoreMV8x8(int);
 extern void   RestoreMV8x8(int);
 extern void   store_macroblock_parameters (Macroblock *currMB, int);
 extern void   SetModesAndRefframeForBlocks (Macroblock *currMB, int);
-extern void   SetRefAndMotionVectors (Macroblock *currMB, int, int, int, int, int);
+extern void   SetRefAndMotionVectors (Macroblock *currMB, int, int, int, int, int, short);
 extern void   StoreNewMotionVectorsBlock8x8(int, int, int, int, int, int, int);
-extern void   assign_enc_picture_params(int, char, int, int, int, int, int);
+extern void   assign_enc_picture_params(int, char, int, int, int, int, int, short);
+extern void   set_subblock8x8_info(Block8x8Info*, int, int, RD_8x8DATA*);
+extern void   set_block8x8_info(Block8x8Info*, int, int, char[2], char, short);
+extern void   update_prediction_for_mode16x16(Block8x8Info*, int, int*);
 extern void   update_refresh_map(int intra, int intra1, Macroblock *currMB);
 extern void   SetMotionVectorsMB (Macroblock*, int);
 extern void   SetCoeffAndReconstruction8x8 (Macroblock*);
@@ -65,20 +62,23 @@ extern int    I16Offset (int, int);
 extern int    CheckReliabilityOfRef (int, int, int, int);
 extern int    Mode_Decision_for_Intra4x4Macroblock (Macroblock *currMB, double, double*);
 extern int    RDCost_for_macroblocks (Macroblock  *currMB, double, int, double*, double*, double*, int);
-extern double RDCost_for_8x8blocks (Macroblock  *currMB, int*, int64*, double, int, int, short, short, short);
+extern double RDCost_for_8x8blocks (Macroblock  *currMB, int*, int64*, double, int, int, short, short, short, short);
 extern double *mb16x16_cost_frame;
 
 extern const int  b8_mode_table[6];
 extern const int  mb_mode_table[9];
 
 void rc_store_diff(int cpix_x, int cpix_y, imgpel prediction[16][16]);
-void submacroblock_mode_decision(RD_PARAMS, RD_8x8DATA *, Macroblock *,int ***, int ***, int ***, int *, short, int, int *, int *, int *, int);
+void submacroblock_mode_decision(RD_PARAMS *, RD_8x8DATA *, Macroblock *,int ***, int ***, int ***, int *, short, int, int *, int *, int *, int);
 void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bslice);
-void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_PARAMS enc_mb, int bmcost[5], char best_ref[2]);
+void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_PARAMS *enc_mb, int bmcost[5], char best_ref[2]);
 void determine_prediction_list(int, int [5], char [2], char *, int *, short *);
-void compute_mode_RD_cost(int mode, Macroblock *currMB, RD_PARAMS enc_mb,
+void compute_mode_RD_cost(int mode, Macroblock *currMB, RD_PARAMS *enc_mb,
                                double *min_rdcost, double *min_dcost, double *min_rate,
                                int i16mode, short bslice, short *inter_skip);
+
+int iminarray ( int arr[], int size, int *minind ); 
+
 extern void update_lambda_costs(RD_PARAMS *enc_mb, int lambda_mf[3]);
 
 
diff --git a/lencod/inc/mv-search.h b/lencod/inc/mv-search.h
index 19831d9..9b83711 100644
--- a/lencod/inc/mv-search.h
+++ b/lencod/inc/mv-search.h
@@ -9,7 +9,6 @@
  * \author
  *    Inge Lille-Langoy               <inge.lille-langoy@telenor.com>   \n
  *    Alexis Michael Tourapis         <alexis.tourapis@dolby.com>       \n
- *    Copyright (C) 1999  Telenor Satellite Services, Norway
  *
  ************************************************************************
  */
@@ -18,7 +17,7 @@
 #define _MV_SEARCH_H_
 
 extern int (*BiPredME)      (Macroblock *, imgpel *, short, int, int, char  ***, short  ****,
-                       int, int, int, short[2], short[2], short[2], short[2], int, int, int, int);
+                       int, int, int, short[2], short[2], short[2], short[2], int, int, int, int, int);
 
 extern int (*SubPelBiPredME)(imgpel* orig_pic, short ref, int list, int pic_pix_x, int pic_pix_y,
                              int blocktype, short pred_mv1[2], short pred_mv2[2], short mv1[2], short mv2[2], 
@@ -30,7 +29,7 @@ extern int (*SubPelME)      (imgpel* orig_pic, short ref, int list, int list_off
 extern void SetMotionVectorPredictor (Macroblock *currMB, short  pmv[2], char   **refPic, short  ***tmp_mv,
                                short  ref_frame, int list, int block_x, int block_y, int blockshape_x, int blockshape_y);
 
-extern void PrepareMEParams(int apply_weights, int ChromaMEEnable, int list, int ref);
+extern void PrepareMEParams      (int apply_weights, int ChromaMEEnable, int list, int ref);
 extern void PrepareBiPredMEParams(int apply_weights, int ChromaMEEnable, int list, int list_offset, int ref);
 
 #endif
diff --git a/lencod/inc/q_around.h b/lencod/inc/q_around.h
new file mode 100644
index 0000000..af5469e
--- /dev/null
+++ b/lencod/inc/q_around.h
@@ -0,0 +1,44 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    q_around.h
+ *
+ * \author
+ *    Alexis Michael Tourapis
+ *
+ * \brief
+ *    Headerfile for Quantization Adaptive Rounding
+ **************************************************************************
+ */
+
+#ifndef _Q_AROUND_H_
+#define _Q_AROUND_H_
+
+extern int   **fadjust8x8, **fadjust4x4, ***fadjust4x4Cr, ***fadjust8x8Cr;
+
+typedef struct around_offset
+{
+  int  **InterFAdjust4x4;
+  int  **IntraFAdjust4x4;
+  int  **InterFAdjust8x8; 
+  int  **IntraFAdjust8x8;
+  int ***InterFAdjust4x4Cr;
+  int ***IntraFAdjust4x4Cr;
+  int ***InterFAdjust8x8Cr;
+  int ***IntraFAdjust8x8Cr;
+} ARoundOffset;
+
+// Create / Clear adaptive rounding variables
+void setup_adaptive_rounding (InputParameters *params);
+void clear_adaptive_rounding (InputParameters *params);
+
+void store_adaptive_rounding_parameters        (Macroblock *currMB, int mode);
+void store_adaptive_rounding_parameters_luma   (Macroblock *currMB, int mode);
+void store_adaptive_rounding_parameters_chroma (Macroblock *currMB, int mode);
+
+void store_adaptive_rounding (ImageParameters *img, int block_y, int block_x);
+void update_adaptive_rounding(ImageParameters *img, int block_y, int block_x);
+void update_offset_params    (Macroblock *currMB, int mode, int luma_transform_size_8x8_flag);
+
+#endif
+
diff --git a/lencod/inc/quant4x4.h b/lencod/inc/quant4x4.h
index 48c16e0..e17d6b4 100644
--- a/lencod/inc/quant4x4.h
+++ b/lencod/inc/quant4x4.h
@@ -15,60 +15,59 @@
 #ifndef _QUANT4x4_H_
 #define _QUANT4x4_H_
 
-void init_quant_4x4(ImageParameters *img);
+void init_quant_4x4(InputParameters *params, ImageParameters *img);
 
-int quant_4x4_normal(int (*tblock)[16], int block_y, int block_x, int qp, 
-                     int*  ACLevel, int*  ACRun, 
-                     int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                     int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_4x4_normal (int (*tblock)[16], int block_y, int block_x, int qp, 
+                      int*  ACLevel, int*  ACRun, 
+                      int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                      int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
 
-int quant_4x4_around(int (*tblock)[16], int block_y, int block_x, int qp, 
-                     int*  ACLevel, int*  ACRun, 
-                     int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                     int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_4x4_around (int (*tblock)[16], int block_y, int block_x, int qp, 
+                      int*  ACLevel, int*  ACRun, 
+                      int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                      int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
 
-int quant_4x4_trellis (int (*tblock)[16], int block_y, int block_x, int qp,
-                       int*  ACLevel, int*  ACRun, 
-                       int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,
+                      int*  ACLevel, int*  ACRun, 
+                      int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                      int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
 
-int (*quant_4x4)    (int (*tblock)[16], int block_y, int block_x, int qp, 
-                     int*  ACLevel, int*  ACRun, 
-                     int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                     int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int (*quant_4x4)     (int (*tblock)[16], int block_y, int block_x, int qp, 
+                      int*  ACLevel, int*  ACRun, 
+                      int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                      int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
 
-int (*quant_4x4cr)    (int (*tblock)[16], int block_y, int block_x, int qp, 
-                     int*  ACLevel, int*  ACRun, 
-                     int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                     int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_dc4x4_normal (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2]);
 
+int quant_dc4x4_around (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2]);
 
-int quant_ac4x4_normal(int (*tblock)[16], int block_y, int block_x, int qp,                 
-                       int*  ACLevel, int*  ACRun, 
-                       int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_dc4x4_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2]);
 
-int quant_ac4x4_around(int (*tblock)[16], int block_y, int block_x, int qp,                 
-                       int*  ACLevel, int*  ACRun, 
-                       int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int (*quant_dc4x4)     (int (*tblock)[4], int qp, int*  DCLevel, int*  DCRun, 
+                        int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2]);
 
-int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,                
+int quant_ac4x4_normal (int (*tblock)[16], int block_y, int block_x, int qp,                 
                         int*  ACLevel, int*  ACRun, 
                         int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
-
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type);
 
-int (*quant_ac4x4)    (int (*tblock)[16], int block_y, int block_x, int qp,                 
-                       int*  ACLevel, int*  ACRun, 
-                       int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_ac4x4_around (int (*tblock)[16], int block_y, int block_x, int qp,                 
+                        int*  ACLevel, int*  ACRun, 
+                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type);
 
-int (*quant_ac4x4cr)  (int (*tblock)[16], int block_y, int block_x, int qp,                 
-                       int*  ACLevel, int*  ACRun, 
-                       int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,                
+                        int*  ACLevel, int*  ACRun, 
+                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type);
 
+int (*quant_ac4x4)     (int (*tblock)[16], int block_y, int block_x, int qp,                 
+                        int*  ACLevel, int*  ACRun, 
+                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type);
 
 #endif
 
diff --git a/lencod/inc/quant8x8.h b/lencod/inc/quant8x8.h
index 78b45e8..50fd773 100644
--- a/lencod/inc/quant8x8.h
+++ b/lencod/inc/quant8x8.h
@@ -15,7 +15,7 @@
 #ifndef _QUANT8x8_H_
 #define _QUANT8x8_H_
 
-void init_quant_8x8(ImageParameters *img);
+void init_quant_8x8(InputParameters *params, ImageParameters *img);
 
 int quant_8x8_normal(int (*tblock)[16], int block_y, int block_x, int qp, 
                      int*  ACLevel, int*  ACRun, 
diff --git a/lencod/inc/quantChroma.h b/lencod/inc/quantChroma.h
new file mode 100644
index 0000000..97c02d3
--- /dev/null
+++ b/lencod/inc/quantChroma.h
@@ -0,0 +1,59 @@
+
+/*!
+************************************************************************
+* \file quant_cr.h
+*
+* \brief
+*    Quantization process for chroma header file
+*
+* \author
+*    Alexis Michael Tourapis         <alexismt@ieee.org>                
+*
+************************************************************************
+*/
+
+#ifndef _QUANT_CR_H_
+#define _QUANT_CR_H_
+
+void init_quant_Chroma(InputParameters *params, ImageParameters *img);
+
+int (*quant_4x4cr)   (int (*tblock)[16], int block_y, int block_x, int qp, 
+                      int*  ACLevel, int*  ACRun, 
+                      int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                      int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost);
+
+int quant_dc2x2_normal (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust2x2, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int quant_dc2x2_around (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust2x2, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int quant_dc2x2_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust, int levelscale, int invlevelscale, int **leveloffset, 
+                        const byte (*pos_scan)[2]);
+
+int quant_dc4x2_normal (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int quant_dc4x2_around (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int quant_dc4x2_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int (*quant_dc_cr)     (int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                        int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                        const byte (*pos_scan)[2]);
+
+int (*quant_ac4x4cr)   (int (*tblock)[16], int block_y, int block_x, int qp,                 
+                        int*  ACLevel, int*  ACRun, 
+                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type);
+
+#endif
+
diff --git a/lencod/inc/ratectl.h b/lencod/inc/ratectl.h
index c99afa6..212ef70 100644
--- a/lencod/inc/ratectl.h
+++ b/lencod/inc/ratectl.h
@@ -53,8 +53,6 @@ typedef struct {
 
 // macroblock activity
 int    diffy[16][16];
-int    qp_mbaff[2][2],       qp_mbaff[2][2];
-int    delta_qp_mbaff[2][2], delta_qp_mbaff[2][2];
 
 // generic functions
 int    Qstep2QP          ( double Qstep );
diff --git a/lencod/inc/rc_quadratic.h b/lencod/inc/rc_quadratic.h
index 07db630..c530336 100644
--- a/lencod/inc/rc_quadratic.h
+++ b/lencod/inc/rc_quadratic.h
@@ -157,7 +157,7 @@ void updatePparams    (rc_quadratic *prc, int complexity );
 void updateBparams    (rc_quadratic *prc, int complexity );
 
 // external generic functions
-void rc_handle_mb         ( int prev_mb, Macroblock *currMB, Slice *curr_slice );
+int  rc_handle_mb         ( int prev_mb, Macroblock *currMB, Slice *curr_slice );
 void rc_init_top_field    ( void );
 void rc_init_bottom_field ( int TopFieldBits );
 void rc_init_frame_rdpic  ( float rateRatio );
diff --git a/lencod/inc/rdo_quant.h b/lencod/inc/rdo_quant.h
index 905bcb6..3728d0e 100644
--- a/lencod/inc/rdo_quant.h
+++ b/lencod/inc/rdo_quant.h
@@ -51,7 +51,14 @@ void est_significant_coefficients (Macroblock* currMB, EncodingEnvironmentPtr ee
 int biari_no_bits(EncodingEnvironmentPtr eep, signed short symbol, BiContextTypePtr bi_ct );
 int biari_state(EncodingEnvironmentPtr eep, signed short symbol, BiContextTypePtr bi_ct );
 
-int est_write_and_store_CBP_block_bit(Macroblock* currMB, int type, int block_y, int block_x);
+void rdoq_dc(int (*tblock)[4], int qp_per, int qp_rem, int levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16], int type);
+int init_trellis_data   (int (*tblock)[16], int block_x, int qp_per, int qp_rem, 
+                         int **levelscale, int **leveloffset, const byte *p_scan, Macroblock *currMB,  
+                         levelDataStruct levelData[], int* kStart, int* kStop, int type);
+int init_trellis_data_DC(int (*tblock)[4], int qp_per, int qp_rem, 
+                         int levelscale, int **leveloffset, const byte *p_scan, Macroblock *currMB,  
+                         levelDataStruct levelData[], int* kStart, int* kStop, int type);
+int est_write_and_store_CBP_block_bit(Macroblock* currMB, int type);
 void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int type, double lambda, int kStart, 
                              int kStop, int noCoeff, int estCBP);
 int est_unary_exp_golomb_level_encode(unsigned int symbol, int ctx, int type);
@@ -59,6 +66,7 @@ int est_unary_exp_golomb_level_encode(unsigned int symbol, int ctx, int type);
 void RDOQ_update_mode(RD_PARAMS *enc_mb, int bslice);
 void copy_rddata_trellis (RD_DATA *dest, RD_DATA *src);
 void updateMV_mp(int *m_cost, short ref, int list, int h, int v, int blocktype, int *lambda_factor, int block8x8);
+void trellis_coding(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb);
 
 #endif  // _RDO_QUANT_H_
 
diff --git a/lencod/inc/rdopt.h b/lencod/inc/rdopt.h
index b9ecd82..0b0072f 100644
--- a/lencod/inc/rdopt.h
+++ b/lencod/inc/rdopt.h
@@ -17,12 +17,6 @@
 #ifndef _RDO_H_
 #define _RDO_H_
 
-extern int   **bestInterFAdjust4x4, **bestIntraFAdjust4x4;
-extern int   **bestInterFAdjust8x8, **bestIntraFAdjust8x8;
-extern int   ***bestInterFAdjust4x4Cr, ***bestIntraFAdjust4x4Cr;
-extern int   ***bestInterFAdjust8x8Cr, ***bestIntraFAdjust8x8Cr;
-extern int   **fadjust8x8, **fadjust4x4, ***fadjust4x4Cr, ***fadjust8x8Cr;
-
 extern int   ****cofAC, ****cofAC8x8;        // [8x8block][4x4block][level/run][scan_pos]
 extern int   ***cofDC;                       // [yuv][level/run][scan_pos]
 extern int   **cofAC4x4, ****cofAC4x4intern; // [level/run][scan_pos]
@@ -30,17 +24,11 @@ extern int   cbp, cbp8x8, cnt_nonz_8x8;
 extern int   cbp_blk8x8;
 extern char  l0_refframe[4][4], l1_refframe[4][4];
 extern short b8mode[4], b8pdir[4];
-extern short best8x8mode [4];                // [block]
-extern char  best8x8pdir  [MAXMODE][4];       // [mode][block]
-extern char  best8x8l0ref [MAXMODE][4];       // [mode][block]
-extern char  best8x8l1ref [MAXMODE][4];       // [mode][block]
-extern char  best8x8ref[2][MAXMODE][4];       // [mode][block]
 
 //CSptr cs_mb, cs_b8, cs_cm, cs_ib8, cs_ib4;
 extern int   best_c_imode;
 extern int   best_i16offset;
 extern short best_mode;
-extern short  bi_pred_me;
 
 //mixed transform sizes definitions
 extern int   luma_transform_size_8x8_flag;
@@ -68,10 +56,15 @@ int valid_intra_mode(int ipmode);
 void compute_comp_cost(imgpel **cur_img, imgpel prd_img[16][16], int pic_opix_x, int *cost);
 void generate_pred_error(imgpel **cur_img, imgpel prd_img[16][16], imgpel cur_prd[16][16], 
                          int m7[16][16], int pic_opix_x, int block_x);
-
-
-void store_adaptive_rounding (int block_y, int block_x);
-void update_adaptive_rounding(int block_y, int block_x);
+extern void SetMotionVectorPredictor (Macroblock *currMB, short  pmv[2], char   **refPic,
+                         short  ***tmp_mv, short  ref_frame,
+                         int    list,      int mb_x, int mb_y, 
+                         int    blockshape_x, int blockshape_y);
+extern void UpdateMotionVectorPredictor(Macroblock* currMB);
+                         
+//============= rate-distortion optimization ===================
+void  clear_rdopt (InputParameters *params);
+void  init_rdopt  (InputParameters *params);
 
 #endif
 
diff --git a/lencod/inc/report.h b/lencod/inc/report.h
new file mode 100644
index 0000000..00966c0
--- /dev/null
+++ b/lencod/inc/report.h
@@ -0,0 +1,25 @@
+
+/*!
+ ************************************************************************
+ * \file report.h
+ *
+ * \brief
+ *    headers for frame format related information
+ *
+ * \author
+ *
+ ************************************************************************
+ */
+#ifndef _REPORT_H_
+#define _REPORT_H_
+#include "contributors.h"
+#include "global.h"
+#include "enc_statistics.h"
+
+void report ( ImageParameters *img, InputParameters *params, StatParameters *stats);
+void information_init ( ImageParameters *img, InputParameters *params, StatParameters *stats);
+void report_frame_statistic(void);
+void report_stats_on_error (void);
+
+#endif
+
diff --git a/lencod/inc/slice.h b/lencod/inc/slice.h
new file mode 100644
index 0000000..af1ee04
--- /dev/null
+++ b/lencod/inc/slice.h
@@ -0,0 +1,37 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    slice.h
+ *
+ * \author
+ *    Athanasios Leontaris
+ *
+ * \date
+ *    16 July 2008
+ *
+ * \brief
+ *    Headerfile for slice-related functions
+ **************************************************************************
+ */
+
+#ifndef _SLICE_H_
+#define _SLICE_H_
+
+#include "global.h"
+#include "mbuffer.h"
+
+void poc_ref_pic_reorder_frame( StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no );
+void poc_ref_pic_reorder_field( StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no );
+
+void init_ref_pic_list_reordering( void );
+int  start_slice( void );
+int  terminate_slice( int lastslice );
+int  encode_one_slice ( int SliceGroupId, Picture *pic, int TotalCodedMBs );
+void init_slice ( int start_mb_addr );
+void free_slice_list( Picture *currPic );
+
+void SetLambda( int j, int qp, double lambda_scale );
+void SetLagrangianMultipliersOn( void );
+void SetLagrangianMultipliersOff( void );
+
+#endif
diff --git a/lencod/inc/vlc.h b/lencod/inc/vlc.h
index 0491b81..ef10173 100644
--- a/lencod/inc/vlc.h
+++ b/lencod/inc/vlc.h
@@ -21,22 +21,22 @@ int u_v  (int n, char *tracestring, int value, Bitstream *bitstream);
 void levrun_linfo_c2x2(int level,int run,int *len,int *info);
 void levrun_linfo_inter(int level,int run,int *len,int *info);
 
-void writeSE_Fix    (SyntaxElement *se, Bitstream *bitstream);
-void writeSE_UVLC   (SyntaxElement *se, DataPartition *dp);
-void writeSE_SVLC   (SyntaxElement *se, DataPartition *dp);
-void writeSE_Flag   (SyntaxElement *se, DataPartition *dp);
-void writeSE_invFlag(SyntaxElement *se, DataPartition *dp);
-void writeSE_Dummy  (SyntaxElement *se, DataPartition *dp);
-
-void writeCBP_VLC   (Macroblock* currMB, SyntaxElement *se, DataPartition *dp);
-void writeIntraPredMode_CAVLC(SyntaxElement *se, DataPartition *dp);
-
-int   writeSyntaxElement2Buf_UVLC(SyntaxElement *se, Bitstream* this_streamBuffer );
-void  writeUVLC2buffer(SyntaxElement *se, Bitstream *currStream);
+void writeSE_Fix                  (SyntaxElement *se, Bitstream *bitstream);
+void writeSE_UVLC                 (SyntaxElement *se, DataPartition *dp);
+void writeSE_SVLC                 (SyntaxElement *se, DataPartition *dp);
+void writeSE_Flag                 (SyntaxElement *se, DataPartition *dp);
+void writeSE_invFlag              (SyntaxElement *se, DataPartition *dp);
+void writeSE_Dummy                (SyntaxElement *se, DataPartition *dp);
+
+void writeCBP_VLC                 (Macroblock* currMB, SyntaxElement *se, DataPartition *dp);
+void writeIntraPredMode_CAVLC     (SyntaxElement *se, DataPartition *dp);
+int   writeSyntaxElement2Buf_UVLC (SyntaxElement *se, Bitstream* this_streamBuffer );
+void  writeUVLC2buffer            (SyntaxElement *se, Bitstream *currStream);
+void writeVlcByteAlign            (Bitstream* currStream);
 int   writeSyntaxElement2Buf_Fixed(SyntaxElement *se, Bitstream* this_streamBuffer );
-int   symbol2uvlc(SyntaxElement *se);
-void  ue_linfo(int n, int dummy, int *len,int *info);
-void  se_linfo(int mvd, int dummy, int *len,int *info);
+int   symbol2uvlc                 (SyntaxElement *se);
+void  ue_linfo       (int n, int dummy, int *len,int *info);
+void  se_linfo       (int mvd, int dummy, int *len,int *info);
 void  cbp_linfo_intra(int cbp, int dummy, int *len,int *info);
 void  cbp_linfo_inter(int cbp, int dummy, int *len,int *info);
 
diff --git a/lencod/inc/wp.h b/lencod/inc/wp.h
index c223899..776f29d 100644
--- a/lencod/inc/wp.h
+++ b/lencod/inc/wp.h
@@ -17,17 +17,23 @@
 #ifndef _WP_H_
 #define _WP_H_
 
+#include "wp_lms.h"
+#include "wp_mcprec.h"
+
+#define DEBUG_WP  0
+
 void InitWP(InputParameters *params);
-void (*EstimateWPPSlice) (int offset);
-void (*EstimateWPBSlice)(void);
-int  (*TestWPPSlice)(int offset);
-int  (*TestWPBSlice)(int method);
+void (*EstimateWPBSlice) (ImageParameters *img, InputParameters *params);
+void (*EstimateWPPSlice) (ImageParameters *img, InputParameters *params, int offset);
+int  (*TestWPPSlice)     (ImageParameters *img, InputParameters *params, int offset);
+int  (*TestWPBSlice)     (ImageParameters *img, InputParameters *params, int method);
+
+void EstimateWPBSliceAlg0(ImageParameters *img, InputParameters *params);
+void EstimateWPPSliceAlg0(ImageParameters *img, InputParameters *params, int offset);
+int  TestWPPSliceAlg0    (ImageParameters *img, InputParameters *params, int offset);
+int  TestWPBSliceAlg0    (ImageParameters *img, InputParameters *params, int method);
 
-void estimate_weighting_factor_B_slice(void);
-void estimate_weighting_factor_P_slice(int offset);
-int  test_wp_P_slice(int offset);
-int  test_wp_B_slice(int method);
+double ComputeImgSum     (imgpel **CurrentImage, int height, int width);
 
-double ComputeImgSum(imgpel **CurrentImage, int height, int width);
 #endif
 
diff --git a/lencod/inc/wp_lms.h b/lencod/inc/wp_lms.h
new file mode 100644
index 0000000..1682058
--- /dev/null
+++ b/lencod/inc/wp_lms.h
@@ -0,0 +1,26 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    wp_lms.h
+ *
+ * \author
+ *    Alexis Michael Tourapis
+ *
+ * \date
+ *    22. February 2008
+ *
+ * \brief
+ *    Headerfile for weighted prediction support using LMS
+ **************************************************************************
+ */
+
+#ifndef _WP_LMS_H_
+#define _WP_LMS_H_
+
+void EstimateWPPSliceAlg1(ImageParameters *img, InputParameters *params, int offset);
+void EstimateWPBSliceAlg1(ImageParameters *img, InputParameters *params);
+int  TestWPPSliceAlg1    (ImageParameters *img, InputParameters *input, int offset);
+int  TestWPBSliceAlg1    (ImageParameters *img, InputParameters *input, int method);
+
+#endif
+
diff --git a/lencod/inc/wp_mcprec.h b/lencod/inc/wp_mcprec.h
new file mode 100644
index 0000000..8684553
--- /dev/null
+++ b/lencod/inc/wp_mcprec.h
@@ -0,0 +1,64 @@
+/*!
+ ***************************************************************************
+ * \file
+ *    wp_mcprec.h
+ *
+ * \brief
+ *    Headerfile for Improved Motion Compensatation Precision Scheme using Weighted Prediction
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Athanasios Leontaris            <aleon@dolby.com>
+ *
+ * \date
+ *    16 July 2008
+ *
+ **************************************************************************
+ */
+
+#ifndef _WP_MCPREC_H_
+#define _WP_MCPREC_H_
+
+
+#define WP_MCPREC_PLUS0       4
+#define WP_MCPREC_PLUS1       5
+#define WP_MCPREC_MINUS0      6
+#define WP_MCPREC_MINUS1      7
+#define WP_MCPREC_MINUS_PLUS0 8
+#define WP_REGULAR            9
+
+typedef struct
+{
+  int PicNum;              // PicNum/FrameNum
+  int POCNum;              // POC
+}
+WeightedPredRefX;
+
+typedef struct
+{
+  int algorithm;
+}
+WPXPass;
+
+typedef struct
+{
+  int               num_wp_ref_list[2];         // num of elements in each of the above matrices [LIST]
+  WeightedPredRefX *wp_ref_list[2];             // structure with reordering and WP information for ref frames [LIST]
+  WPXPass          *curr_wp_rd_pass;
+  WPXPass           wp_rd_passes[3];            // frame_picture [0...4] (MultiRefWeightedPred == 2)
+}
+WPXObject;
+
+WPXObject *pWPX;
+
+void   wpxInitWPXObject( void );
+void   wpxFreeWPXObject( void );
+void   wpxInitWPXPasses( InputParameters *params );
+void   wpxModifyRefPicList( ImageParameters *img );
+// Note that at some point, InputParameters params contents should be copied into ImageParameters *img. 
+// This would eliminate need of having to use both structures
+int    wpxDetermineWP( InputParameters *params, ImageParameters *img, int clist, int n );
+void   wpxAdaptRefNum( ImageParameters *img );
+void   wpxReorderLists( ImageParameters *img, Slice *currSlice );
+
+#endif
+
diff --git a/lencod/src/block.c b/lencod/src/block.c
index 8c946a8..5ddc54d 100644
--- a/lencod/src/block.c
+++ b/lencod/src/block.c
@@ -24,6 +24,7 @@
 #include <math.h>
 
 #include "global.h"
+#include "enc_statistics.h"
 
 #include "image.h"
 #include "mb_access.h"
@@ -34,39 +35,7 @@
 #include "q_offsets.h"
 #include "q_matrix.h"
 #include "quant4x4.h"
-
-const int quant_coef[6][4][4] = {
-  {{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243},{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243}},
-  {{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660},{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660}},
-  {{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194},{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194}},
-  {{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647},{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647}},
-  {{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355},{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355}},
-  {{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893},{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893}}
-};
-
-const int dequant_coef[6][4][4] = {
-  {{10, 13, 10, 13},{ 13, 16, 13, 16},{10, 13, 10, 13},{ 13, 16, 13, 16}},
-  {{11, 14, 11, 14},{ 14, 18, 14, 18},{11, 14, 11, 14},{ 14, 18, 14, 18}},
-  {{13, 16, 13, 16},{ 16, 20, 16, 20},{13, 16, 13, 16},{ 16, 20, 16, 20}},
-  {{14, 18, 14, 18},{ 18, 23, 18, 23},{14, 18, 14, 18},{ 18, 23, 18, 23}},
-  {{16, 20, 16, 20},{ 20, 25, 20, 25},{16, 20, 16, 20},{ 20, 25, 20, 25}},
-  {{18, 23, 18, 23},{ 23, 29, 23, 29},{18, 23, 18, 23},{ 23, 29, 23, 29}}
-};
-static const int A[4][4] = {
-  { 16, 20, 16, 20},
-  { 20, 25, 20, 25},
-  { 16, 20, 16, 20},
-  { 20, 25, 20, 25}
-};
-
-
-const byte QP_SCALE_CR[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
-};
+#include "quantChroma.h"
 
 // Notation for comments regarding prediction and predictors.
 // The pels of the 4x4 block are labelled a..p. The predictor pels above
@@ -94,19 +63,27 @@ const byte QP_SCALE_CR[52]=
 #define P_K (PredPel[11])
 #define P_L (PredPel[12])
 
+extern const unsigned char subblk_offset_y[3][8][4];
+extern const unsigned char subblk_offset_x[3][8][4];
 // global pointers for 4x4 quantization parameters
 extern int ****ptLevelOffset4x4;
 static int **levelscale = NULL, **leveloffset = NULL;
 static int **invlevelscale = NULL;
+static int **levelscale_sp = NULL, **leveloffset_sp = NULL;
+static int **invlevelscale_sp = NULL;
 static int **fadjust4x4 = NULL;
+static int **fadjust2x2 = NULL;
+static int **fadjust4x2 = NULL; // note that this is in fact 2x4 but the coefficients have been transposed for better memory access
 static int **levelscaleDC = NULL, **leveloffsetDC = NULL;
 static int **invlevelscaleDC = NULL;
 static int M1[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
 static int M4[4][4];
 
-int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x);
-int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode);
-int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode);
+//For residual DPCM
+static int Residual_DPCM_4x4_for_Intra16x16(int mb_ores[4][4], int ipmode);
+static int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode);
+static int Residual_DPCM_4x4(int ipmode, int mb_ores[16][16], int mb_rres[16][16], int block_y, int block_x);  
+static int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x);
 
 /*!
  ************************************************************************
@@ -566,11 +543,9 @@ void intrapred_16x16(Macroblock *currMB, ColorPlane pl)
  */
 int dct_16x16(Macroblock *currMB, ColorPlane pl, int new_intra_mode)
 {
-  //int qp_const;
   int i,j;
   int ii,jj;
-   
-  int run,scan_pos,coeff_ctr,level;
+
   int ac_coef = 0;
   static imgpel *img_Y, *predY;
   int nonzero = FALSE;
@@ -594,7 +569,6 @@ int dct_16x16(Macroblock *currMB, ColorPlane pl, int new_intra_mode)
 
   int qp_per = qp_per_matrix[qp];
   int qp_rem = qp_rem_matrix[qp];
-  int q_bits = Q_BITS + qp_per + 1;
 
   // select scaling parameters
   levelscale    = LevelScale4x4Comp[pl][1][qp_rem];
@@ -613,105 +587,88 @@ int dct_16x16(Macroblock *currMB, ColorPlane pl, int new_intra_mode)
     }
   }
 
-    // forward 4x4 DCT
-    for (j = 0; j < 16; j+=4)
+  // forward 4x4 DCT
+  for (j = 0; j < 16; j+=4)
+  {
+    for (i = 0;i < 16; i+=4)
     {
-      for (i = 0;i < 16; i+=4)
-      {
-        forward4x4(M1, M1, j, i);
-      }
+      forward4x4(M1, M1, j, i);
     }
+  }
 
-    // pick out DC coeff
-    for (j = 0; j < 4; j++)
-      for (i = 0; i < 4; i++)
-        M4[j][i]= M1[j << 2][i << 2];
+  // pick out DC coeff
+  for (j = 0; j < 4; j++)
+    for (i = 0; i < 4; i++)
+      M4[j][i]= M1[j << 2][i << 2];
 
-    // hadamard of DC coefficients
-    hadamard4x4(M4, M4);
+  // hadamard of DC coefficients
+  hadamard4x4(M4, M4);
 
-    // quant
-    run=-1;
-    scan_pos=0;
-    
-    for (coeff_ctr=0;coeff_ctr<16;coeff_ctr++)
-    {
-      i=pos_scan[coeff_ctr][0];
-      j=pos_scan[coeff_ctr][1];
+  nonzero = quant_dc4x4(&M4[0], qp, DCLevel, DCRun, levelscale[0][0], invlevelscale[0][0], leveloffset, pos_scan);
 
-      run++;
-      level= (iabs(M4[j][i]) * levelscale[0][0] + (leveloffset[0][0]<<1)) >> q_bits;
+  // inverse DC transform
+  if (nonzero)
+  {
+    ihadamard4x4(M4, M4);
 
-      if (level != 0)
+    // Reset DC coefficients
+    for (j = 0; j < 4; j++)
+    {
+      for (i = 0; i<4;i++)
       {
-        nonzero = TRUE;
-        if (params->symbol_mode == CAVLC && img->qp < 10)
-          level = imin(level, CAVLC_LEVEL_LIMIT);
-
-        level = isignab(level, M4[j][i]);
-        DCLevel[scan_pos  ] = level;
-        DCRun  [scan_pos++] = run;
-        run=-1;
-        M4[j][i] = level;
+        M1[j<<2][i<<2] = rshift_rnd_sf(((M4[j][i]) * invlevelscale[0][0]) << qp_per, 6);
       }
-      else
-        M4[j][i] = 0;
     }
-    DCLevel[scan_pos]=0;
-
-    // inverse DC transform
-    if (nonzero)
-    {
-      ihadamard4x4(M4, M4);
-
-      // Reset DC coefficients
-      for (j=0;j<4;j++)
-        for (i=0;i<4;i++)
-          M1[j<<2][i<<2] = rshift_rnd_sf(((M4[j][i]) * invlevelscale[0][0]) << qp_per, 6);
-    }
-    else // All DC equal to 0.
+  }
+  else // All DC equal to 0.
+  {
+    for (j=0;j<4;j++)
     {
-      for (j=0;j<4;j++)
-        for (i=0;i<4;i++)
-          M1[j<<2][i<<2] = 0;
+      for (i=0;i<4;i++)
+      {
+        M1[j<<2][i<<2] = 0;
+      }
     }
+  }
 
-    // AC processing for MB
-    for (jj=0;jj<4;jj++)
+  // AC processing for MB
+  for (jj=0;jj<4;jj++)
+  {
+    jpos = (jj << 2);
+    for (ii=0;ii<4;ii++)
     {
-      jpos = (jj << 2);
-      for (ii=0;ii<4;ii++)
-      {
-        ipos = (ii << 2);
+      ipos = (ii << 2);
 
-        b8       = 2*(jj >> 1) + (ii >> 1);
-        b4       = 2*(jj & 0x01) + (ii & 0x01);
-        ACLevel  = cofAC[b8][b4][0];
-        ACRun    = cofAC[b8][b4][1];
+      b8       = 2*(jj >> 1) + (ii >> 1);
+      b4       = 2*(jj & 0x01) + (ii & 0x01);
+      ACLevel  = cofAC[b8][b4][0];
+      ACRun    = cofAC[b8][b4][1];
+      img->subblock_y = jj;
+      img->subblock_x = ii;
 
-        // Quantization process
-        nonzero = quant_ac4x4(&M1[jpos], jpos, ipos, qp, ACLevel, ACRun, &fadjust4x4[jpos], 
-          levelscale, invlevelscale, leveloffset, &coeff_cost, pos_scan, COEFF_COST4x4[params->disthres]);
+      // Quantization process
+      nonzero = quant_ac4x4(&M1[jpos], jpos, ipos, qp, ACLevel, ACRun, &fadjust4x4[jpos], 
+        levelscale, invlevelscale, leveloffset, &coeff_cost, pos_scan, COEFF_COST4x4[params->disthres], LUMA_16AC);
 
-        if (nonzero)
-          ac_coef = 15;
+      if (nonzero)
+        ac_coef = 15;
 
-        //IDCT
-        if (M1[jpos][ipos]!= 0 || nonzero)
-          inverse4x4(M1, M1, jpos, ipos);
-      }
+      //IDCT
+      if (M1[jpos][ipos]!= 0 || nonzero)
+        inverse4x4(M1, M1, jpos, ipos);
     }
+  }
 
 
     // Reconstruct samples
     SampleReconstruct (img_enc, curr_mpr_16x16[new_intra_mode], M1, 0, 0, img->pix_y, img->pix_x, 16, 16, max_imgpel_value, DQ_BITS);
 
-    if(img->type == SP_SLICE)
-    {
-      for (j = img->pix_y; j < img->pix_y + 16;j++)
-        for (i = img->pix_x; i < img->pix_x + 16;i++)
-          lrec[j][i]=-16; //signals an I16 block in the SP frame
-    }
+  if(img->type == SP_SLICE)
+  {
+    for (j = img->pix_y; j < img->pix_y + 16;j++)
+      for (i = img->pix_x; i < img->pix_x + 16;i++)
+        lrec[j][i]=-16; //signals an I16 block in the SP frame
+  }
 
   return ac_coef;
 }
@@ -824,7 +781,7 @@ int dct_16x16_ls(Macroblock *currMB, ColorPlane pl, int new_intra_mode)
         j=pos_scan[coeff_ctr][1];
 
         run++;
-        *m7 = M4[j][i];
+        m7 = &M4[j][i];
 
         if (*m7 != 0)
         {
@@ -891,7 +848,7 @@ int dct_4x4(Macroblock *currMB, ColorPlane pl, int block_x,int block_y, int *coe
 {
   int j;
 
-  int nonzero = FALSE;  
+  int nonzero = FALSE;
 
   int   pos_x   = block_x >> BLOCK_SHIFT;
   int   pos_y   = block_y >> BLOCK_SHIFT;
@@ -901,8 +858,9 @@ int dct_4x4(Macroblock *currMB, ColorPlane pl, int block_x,int block_y, int *coe
   int*  ACRun   = img->cofAC[b8][b4][1];
 
   imgpel **img_enc      = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl]; 
 
   int   max_imgpel_value = img->max_imgpel_value;
   int   qp = currMB->qp_scaled[pl]; 
@@ -916,31 +874,33 @@ int dct_4x4(Macroblock *currMB, ColorPlane pl, int block_x,int block_y, int *coe
   leveloffset   = ptLevelOffset4x4[intra][qp];
 
   fadjust4x4    = img->AdaptiveRounding ? (pl ? &img->fadjust4x4Cr[pl-1][intra][block_y] : &img->fadjust4x4[intra][block_y]) : NULL;
+  img->subblock_x = ((b8&0x1)==0) ? (((b4&0x1)==0)? 0: 1) : (((b4&0x1)==0)? 2: 3); // horiz. position for coeff_count context
+  img->subblock_y = (b8<2)        ? ((b4<2)       ? 0: 1) : ((b4<2)       ? 2: 3); // vert.  position for coeff_count context
 
   //  Forward 4x4 transform
-  forward4x4(curr_res, M1, block_y, block_x);
+  forward4x4(mb_ores, M1, block_y, block_x);
 
   // Quantization process
   nonzero = quant_4x4(&M1[block_y], block_y, block_x, qp, ACLevel, ACRun, fadjust4x4, 
     levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST4x4[params->disthres]);
 
+  //  Decoded block moved to frame memory
   if (nonzero)
   {
     // Inverse 4x4 transform
-    inverse4x4(M1, curr_res, block_y, block_x);
+    inverse4x4(M1, mb_rres, block_y, block_x);
 
     // generate final block
-    SampleReconstruct (img_enc, curr_mpr, curr_res, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE, BLOCK_SIZE, max_imgpel_value, DQ_BITS);
+    SampleReconstruct (img_enc, mb_pred, mb_rres, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE, BLOCK_SIZE, max_imgpel_value, DQ_BITS);
   }
   else // if (nonzero) => No transformed residual. Just use prediction.
   {
     for (j=block_y; j < block_y + BLOCK_SIZE; j++)
     {
-      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(curr_mpr[j][block_x]), BLOCK_SIZE * sizeof(imgpel));
+      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE * sizeof(imgpel));
     }
   }
 
-  //  Decoded block moved to frame memory
   return nonzero;
 }
 
@@ -982,18 +942,19 @@ int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
 
   int   pix_y, pix_x;
   imgpel **img_enc       = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl]; 
   int   *m7;
 
   const byte *p_scan = currMB->is_field_mode ? &FIELD_SCAN[0][0] : &SNGL_SCAN[0][0];
 
   // select scaling parameters
-  fadjust4x4    = img->AdaptiveRounding ? &img->fadjust4x4[intra][block_y] : NULL;
+  fadjust4x4 = img->AdaptiveRounding ? &img->fadjust4x4[intra][block_y] : NULL;
 
-  if((ipmode_DPCM < 2))
+  if( (ipmode_DPCM < 2) && (intra))
   {
-    Residual_DPCM_4x4(ipmode_DPCM, curr_res, block_y, block_x);
+    Residual_DPCM_4x4(ipmode_DPCM, mb_ores, mb_rres, block_y, block_x);
   }
 
   for (coeff_ctr=0;coeff_ctr < 16;coeff_ctr++)
@@ -1002,8 +963,8 @@ int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
     j = *p_scan++;
 
     run++;
-    
-    m7 = &curr_res[j+block_y][i+block_x];    
+
+    m7 = &mb_rres[j+block_y][i+block_x];    
 
     if (img->AdaptiveRounding)
       fadjust4x4[j][block_x+i] = 0;
@@ -1022,9 +983,9 @@ int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
   }
   *ACL = 0;
 
-  if(ipmode_DPCM<2)  //For residual DPCM
+  if( (ipmode_DPCM < 2) && (intra))
   {
-    Inv_Residual_DPCM_4x4(curr_res, block_y, block_x);
+    Inv_Residual_DPCM_4x4(mb_rres, block_y, block_x);
   }
 
   for (j=0; j < BLOCK_SIZE; j++)
@@ -1033,14 +994,13 @@ int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
     pix_x = img->pix_x+block_x;
     for (i=0; i < BLOCK_SIZE; i++)
     {
-      img_enc[pix_y][pix_x+i] = curr_res[j+block_y][i+block_x] + curr_mpr[j+block_y][i+block_x];
+      img_enc[pix_y][pix_x+i] = mb_rres[j+block_y][i+block_x] + mb_pred[j+block_y][i+block_x];
     }
   }
 
   return nonzero;
 }
 
-
 /*!
 ************************************************************************
 * \brief
@@ -1050,45 +1010,54 @@ int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
 *    block_x,block_y: Block position inside a macro block (0,4,8,12).
 ************************************************************************
 */
-int Residual_DPCM_4x4(int ipmode, int m7[16][16], int block_y, int block_x)
+static int Residual_DPCM_4x4(int ipmode, int mb_ores[16][16], int mb_rres[16][16], int block_y, int block_x)
 {
-  int i,j;
+  int i;
   int temp[4][4];
 
   if(ipmode==VERT_PRED)
   {
+    temp[0][0] = mb_ores[block_y][block_x    ];
+    temp[0][1] = mb_ores[block_y][block_x + 1];
+    temp[0][2] = mb_ores[block_y][block_x + 2];
+    temp[0][3] = mb_ores[block_y][block_x + 3];
 
     for (i=1; i<4; i++) 
     {
-      temp[i][0] = m7[block_y + i][block_x    ] - m7[block_y + i - 1][block_x    ];
-      temp[i][1] = m7[block_y + i][block_x + 1] - m7[block_y + i - 1][block_x + 1];
-      temp[i][2] = m7[block_y + i][block_x + 2] - m7[block_y + i - 1][block_x + 2];
-      temp[i][3] = m7[block_y + i][block_x + 3] - m7[block_y + i - 1][block_x + 3];
+      temp[i][0] = mb_ores[block_y + i][block_x    ] - mb_ores[block_y + i - 1][block_x    ];
+      temp[i][1] = mb_ores[block_y + i][block_x + 1] - mb_ores[block_y + i - 1][block_x + 1];
+      temp[i][2] = mb_ores[block_y + i][block_x + 2] - mb_ores[block_y + i - 1][block_x + 2];
+      temp[i][3] = mb_ores[block_y + i][block_x + 3] - mb_ores[block_y + i - 1][block_x + 3];
     }
 
-    for (i=1; i<4; i++)
+    for (i = 0; i < 4; i++)
     {
-      m7[block_y+i][block_x    ] = temp[i][0];
-      m7[block_y+i][block_x + 1] = temp[i][1];
-      m7[block_y+i][block_x + 2] = temp[i][2];
-      m7[block_y+i][block_x + 3] = temp[i][3];
+      mb_ores[block_y+i][block_x    ] = temp[i][0];
+      mb_ores[block_y+i][block_x + 1] = temp[i][1];
+      mb_ores[block_y+i][block_x + 2] = temp[i][2];
+      mb_ores[block_y+i][block_x + 3] = temp[i][3];
     }
   }
   else  //HOR_PRED
   {
+    temp[0][0] = mb_ores[block_y    ][block_x];
+    temp[1][0] = mb_ores[block_y + 1][block_x];
+    temp[2][0] = mb_ores[block_y + 2][block_x];
+    temp[3][0] = mb_ores[block_y + 3][block_x];
+
     for (i=0; i<4; i++)
-      for (j=1; j<4; j++)
-      {
-        temp[i][1] = m7[block_y + i][block_x + 1] - m7[block_y + i][block_x    ];
-        temp[i][2] = m7[block_y + i][block_x + 2] - m7[block_y + i][block_x + 1];
-        temp[i][3] = m7[block_y + i][block_x + 3] - m7[block_y + i][block_x + 2];
-      }
+    {
+      temp[i][1] = mb_ores[block_y + i][block_x + 1] - mb_ores[block_y + i][block_x    ];
+      temp[i][2] = mb_ores[block_y + i][block_x + 2] - mb_ores[block_y + i][block_x + 1];
+      temp[i][3] = mb_ores[block_y + i][block_x + 3] - mb_ores[block_y + i][block_x + 2];
+    }
 
     for (i=0; i<4; i++)
     {
-      m7[block_y+i][block_x + 1] = temp[i][1];
-      m7[block_y+i][block_x + 2] = temp[i][2];
-      m7[block_y+i][block_x + 3] = temp[i][3];
+      mb_ores[block_y + i][block_x + 0] = temp[i][0];
+      mb_ores[block_y + i][block_x + 1] = temp[i][1];
+      mb_ores[block_y + i][block_x + 2] = temp[i][2];
+      mb_ores[block_y + i][block_x + 3] = temp[i][3];
     }
   }
   return 0;
@@ -1104,7 +1073,7 @@ int Residual_DPCM_4x4(int ipmode, int m7[16][16], int block_y, int block_x)
 ************************************************************************
 */
 //For residual DPCM
-int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x)  
+static int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x)  
 {
   int i;
   int temp[4][4];
@@ -1153,7 +1122,7 @@ int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x)
 ************************************************************************
 */
 //For residual DPCM
-int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
+static int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
 {
   int i,j;
   int temp[4][4];
@@ -1173,9 +1142,9 @@ int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)
     for (i=0; i<4; i++)
       for (j=1; j<4; j++)
         temp[i][j] = m7[i][j] - m7[i][j-1];
-    
-      for (i=0; i<4; i++)
-        for (j=1; j<4; j++)
+
+    for (i=0; i<4; i++)
+      for (j=1; j<4; j++)
         m7[i][j] = temp[i][j];
   }
   return 0;
@@ -1187,7 +1156,7 @@ int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)
 ************************************************************************
 */
 //For residual DPCM
-int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
+static int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
 {
   int i;
   int temp[4][4];
@@ -1246,11 +1215,13 @@ int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)
  */
 int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
 {
-  int i,j,n2,n1,coeff_ctr,level ,scan_pos,run;
-  static int m1[BLOCK_SIZE],m5[BLOCK_SIZE];
-  int coeff_cost;
-  int cr_cbp_tmp;
-  int DCcoded=0 ;
+  int i, j, n2, n1, coeff_ctr;
+  static int m1[BLOCK_SIZE];
+  int coeff_cost = 0;
+  int cr_cbp_tmp = 0;
+  int DCzero = FALSE;
+  int nonzero[4][4] = {{FALSE}};
+  int nonezero = FALSE;
 
   const byte *c_cost = COEFF_COST4x4[params->disthres];
 
@@ -1265,154 +1236,100 @@ int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
   //FRExt
   static const int64 cbpblk_pattern[4]={0, 0xf0000, 0xff0000, 0xffff0000};
   int yuv = img->yuv_format;
-  int b8;
-  static int m3[4][4];
-  int qp_per_dc = 0;
-  int qp_rem_dc = 0;
-  int q_bits_422 = 0;
+  int b8;  
+
   const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
-  int cur_qp = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;
-  int cur_qp_dc = currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale;
+  int cur_qp = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;  
 
-  int qp_per = qp_per_matrix[cur_qp];
   int qp_rem = qp_rem_matrix[cur_qp];
-  int q_bits = Q_BITS + qp_per + 1;
-  int max_imgpel_value_uv = img->max_imgpel_value_comp[1];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[uv + 1]; 
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[uv + 1]; 
-  int nonzero[4][4] = {{FALSE}};
-  int nonezero = FALSE;
+
+  int max_imgpel_value_uv = img->max_imgpel_value_comp[uv + 1];
+
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1];
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 
 
   levelscale    = LevelScale4x4Comp   [uv + 1][intra][qp_rem];
   leveloffset   = LevelOffset4x4Comp  [uv + 1][intra][cur_qp];
   invlevelscale = InvLevelScale4x4Comp[uv + 1][intra][qp_rem];
   fadjust4x4    = img->AdaptiveRounding ? img->fadjust4x4Cr[intra][uv] : NULL;
+  img->is_v_block = uv;
 
   //============= dct transform ===============
   for (n2=0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
   {
     for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
     {
-      forward4x4(curr_res, curr_res, n2, n1);
+      forward4x4(mb_ores, mb_rres, n2, n1);
     }
   }
 
   if (yuv == YUV420)
   {
     //================== CHROMA DC YUV420 ===================
-    //     2X2 transform of DC coeffs.
-    run=-1;
-    scan_pos=0;
-    
+  
     // forward 2x2 hadamard
-    hadamard2x2(curr_res, m1);
+    hadamard2x2(mb_rres, m1);
 
-    //     Quant of chroma 2X2 coeffs.
-    for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
-    {
-      run++;
-
-      level =(iabs(m1[coeff_ctr]) * levelscale[0][0] + (leveloffset[0][0]<<1)) >> q_bits;
-
-      if (level  != 0)
-      {
-        if (params->symbol_mode == CAVLC && img->qp < 4)
-          level = imin(level, CAVLC_LEVEL_LIMIT);
+    // Quantization process of chroma 2X2 hadamard transformed DC coeffs.
+    DCzero = quant_dc_cr(&m1, cur_qp, DCLevel, DCRun, fadjust2x2, levelscale[0][0], invlevelscale[0][0], leveloffset, SCAN_YUV420);
 
+    if (DCzero) 
+    {
         currMB->cbp_blk |= 0xf0000 << (uv << 2) ;    // if one of the 2x2-DC levels is != 0 set the
         cr_cbp=imax(1,cr_cbp);                     // coded-bit all 4 4x4 blocks (bit 16-19 or 20-23)
-        DCcoded = 1;
-        level = isignab(level, m1[coeff_ctr]);
-        DCLevel[scan_pos  ] = level;
-        DCRun  [scan_pos++] = run;
-        run=-1;          
-        m1[coeff_ctr] = level;
-      }
-      else
-        m1[coeff_ctr] = 0;
     }
 
-    DCLevel[scan_pos] = 0;
     //  Inverse transform of 2x2 DC levels
-    ihadamard2x2(m1, m5);
+    ihadamard2x2(m1, m1);
 
-    curr_res[0][0] = ((m5[0] * invlevelscale[0][0]) << qp_per) >> 5;
-    curr_res[0][4] = ((m5[1] * invlevelscale[0][0]) << qp_per) >> 5;
-    curr_res[4][0] = ((m5[2] * invlevelscale[0][0]) << qp_per) >> 5;
-    curr_res[4][4] = ((m5[3] * invlevelscale[0][0]) << qp_per) >> 5;
+    mb_rres[0][0] = m1[0];
+    mb_rres[0][4] = m1[1];
+    mb_rres[4][0] = m1[2];
+    mb_rres[4][4] = m1[3];
   }
-  else if(yuv == YUV422)
+  else if (yuv == YUV422)
   {
     //for YUV422 only
-    qp_per_dc = qp_per_matrix[cur_qp_dc];
-    qp_rem_dc = qp_rem_matrix[cur_qp_dc];
+    int cur_qp_dc = currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale;
+    int qp_rem_dc = qp_rem_matrix[cur_qp_dc];
 
     invlevelscaleDC = InvLevelScale4x4Comp[uv + 1][intra][qp_rem_dc];
     levelscaleDC    = LevelScale4x4Comp   [uv + 1][intra][qp_rem_dc];
     leveloffsetDC   = LevelOffset4x4Comp  [uv + 1][intra][cur_qp_dc];
 
-    q_bits_422 = Q_BITS + qp_per_dc + 1;
-
     //================== CHROMA DC YUV422 ===================
-    //transform DC coeff
-    //horizontal
-
     //pick out DC coeff    
     for (j=0; j < img->mb_cr_size_y; j+=BLOCK_SIZE)
     {
       for (i=0; i < img->mb_cr_size_x; i+=BLOCK_SIZE)
-        m3[i>>2][j>>2]= curr_res[j][i];
+        M4[i>>2][j>>2]= mb_rres[j][i];
     }
-    // forward transform. Note that coeffs have been transposed (4x2 instead of 2x4) which makes transform a bit faster
-    hadamard4x2(m3, M4);
-
-    run=-1;
-    scan_pos=0;
 
-    //quant of chroma DC-coeffs
-    for (coeff_ctr=0;coeff_ctr<8;coeff_ctr++)
-    {
-      i = SCAN_YUV422[coeff_ctr][0];
-      j = SCAN_YUV422[coeff_ctr][1];
+    // forward hadamard transform. Note that coeffs have been transposed (4x2 instead of 2x4) which makes transform a bit faster
+    hadamard4x2(M4, M4);
 
-      run++;
+    // Quantization process of chroma transformed DC coeffs.
+    DCzero = quant_dc_cr(M4, cur_qp_dc, DCLevel, DCRun, fadjust4x2, levelscaleDC[0][0], invlevelscaleDC[0][0], leveloffsetDC, SCAN_YUV422);
 
-      level =(iabs(M4[i][j]) * levelscaleDC[0][0] + (leveloffsetDC[0][0]<<1)) >> q_bits_422;
-
-      if (level != 0)
-      {
-        //YUV422
-        currMB->cbp_blk |= 0xff0000 << (uv << 3) ;   // if one of the DC levels is != 0 set the
-        cr_cbp=imax(1,cr_cbp);                       // coded-bit all 4 4x4 blocks (bit 16-31 or 32-47) //YUV444
-        DCcoded = 1 ;
-        
-        level = isignab(level,M4[i][j]);
-        DCLevel[scan_pos  ] = level;
-        DCRun  [scan_pos++] = run;
-        run=-1;
-        m3[i][j] = level;
-      }
-      else
-        m3[i][j] = 0;     
+    if (DCzero)
+    {
+      currMB->cbp_blk |= 0xff0000 << (uv << 3) ;   // if one of the DC levels is != 0 set the
+      cr_cbp=imax(1,cr_cbp);                       // coded-bit all 4 4x4 blocks (bit 16-31 or 32-47) //YUV444
     }
-    DCLevel[scan_pos]=0;
-
 
     //inverse DC transform. Note that now M4 is transposed back
-    ihadamard4x2(m3, M4);    
+    ihadamard4x2(M4, M4);    
 
     // This code assumes sizeof(int) > 16. Therefore, no need to have conditional
     for (j = 0; j < 4; j++)
     {
-      curr_res[j << 2 ][0] = rshift_rnd_sf(((M4[j][0]) * invlevelscaleDC[0][0]) << qp_per_dc, 6);
-      curr_res[j << 2 ][4] = rshift_rnd_sf(((M4[j][1]) * invlevelscaleDC[0][0]) << qp_per_dc, 6);
+      mb_rres[j << 2 ][0] = M4[j][0];
+      mb_rres[j << 2 ][4] = M4[j][1];
     }
   }
 
   //     Quant of chroma AC-coeffs.
-  coeff_cost=0;
-  cr_cbp_tmp=0;
-
   for (b8=0; b8 < (img->num_blk8x8_uv >> 1); b8++)
   {
     for (b4=0; b4 < 4; b4++)
@@ -1422,17 +1339,16 @@ int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
       n2 = ver_offset[yuv][b8][b4];
       ACLevel = img->cofAC[4 + b8 + uv_scale][b4][0];
       ACRun   = img->cofAC[4 + b8 + uv_scale][b4][1];
-      run=-1;
-      scan_pos=0;
-
+      img->subblock_y = subblk_offset_y[img->yuv_format - 1][b8][b4]>>2;
+      img->subblock_x = subblk_offset_x[img->yuv_format - 1][b8][b4]>>2;
       // Quantization process
-      nonzero[n2>>2][n1>>2] = quant_ac4x4cr(&curr_res[n2], n2, n1, cur_qp, ACLevel, ACRun, &fadjust4x4[n2], 
-        levelscale, invlevelscale, leveloffset, &coeff_cost, pos_scan, c_cost);
+      nonzero[n2>>2][n1>>2] = quant_ac4x4cr(&mb_rres[n2], n2, n1, cur_qp, ACLevel, ACRun, &fadjust4x4[n2], 
+        levelscale, invlevelscale, leveloffset, &coeff_cost, pos_scan, c_cost, CHROMA_AC);
 
       if (nonzero[n2>>2][n1>>2])
       {
         currMB->cbp_blk |= uv_cbpblk;
-        cr_cbp_tmp=2;
+        cr_cbp_tmp = 2;
         nonezero = TRUE;
       }
     }
@@ -1457,14 +1373,14 @@ int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
           ACLevel = img->cofAC[4 + b8 + uv_scale][b4][0];
           ACRun   = img->cofAC[4 + b8 + uv_scale][b4][1];
 
-          if (DCcoded == 0)
+          if (DCzero == 0)
             currMB->cbp_blk &= ~(uv_cbpblk);  // if no chroma DC's: then reset coded-bits of this chroma subblock
 
           ACLevel[0] = 0;
 
           for (coeff_ctr=1; coeff_ctr < 16; coeff_ctr++)// ac coeff
           {
-            curr_res[n2 + pos_scan[coeff_ctr][1]][n1 + pos_scan[coeff_ctr][0]] = 0;
+            mb_rres[n2 + pos_scan[coeff_ctr][1]][n1 + pos_scan[coeff_ctr][0]] = 0;
             ACLevel[coeff_ctr]  = 0;
           }
         }
@@ -1482,9 +1398,9 @@ int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
   {
     for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
     {
-      if (curr_res[n2][n1] != 0 || nonzero[n2>>2][n1>>2] == TRUE)
+      if (mb_rres[n2][n1] != 0 || nonzero[n2>>2][n1>>2] == TRUE)
       {
-        inverse4x4(curr_res, curr_res, n2, n1);
+        inverse4x4(mb_rres, mb_rres, n2, n1);
         nonezero = TRUE;
       }
     }
@@ -1493,13 +1409,13 @@ int dct_chroma(Macroblock *currMB, int uv, int cr_cbp)
   //  Decoded block moved to memory
   if (nonezero == TRUE)
   {
-    SampleReconstruct (enc_picture->imgUV[uv], curr_mpr, curr_res, 0, 0, img->pix_c_y, img->pix_c_x, img->mb_cr_size_x, img->mb_cr_size_y, max_imgpel_value_uv, DQ_BITS);
+    SampleReconstruct (enc_picture->imgUV[uv], mb_pred, mb_rres, 0, 0, img->pix_c_y, img->pix_c_x, img->mb_cr_size_x, img->mb_cr_size_y, max_imgpel_value_uv, DQ_BITS);
   }
   else
   {
     for (j=0; j < img->mb_cr_size_y; j++)
     {
-      memcpy(&enc_picture->imgUV[uv][img->pix_c_y + j][img->pix_c_x], curr_mpr[j], img->mb_cr_size_x * sizeof(imgpel));
+      memcpy(&enc_picture->imgUV[uv][img->pix_c_y + j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
     }
   }
 
@@ -1529,7 +1445,7 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
   static int m1[BLOCK_SIZE];
   int coeff_cost;
   int cr_cbp_tmp;
-  int DCcoded=0 ;
+  int nonzero = FALSE;
   static imgpel *orig_img, *pred_img;
 
   int   b4;
@@ -1548,8 +1464,9 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
 
   const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
 
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[uv + 1]; 
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[uv + 1]; 
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1];
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 
 
   fadjust4x4    = img->AdaptiveRounding ? img->fadjust4x4Cr[intra][uv] : NULL;
 
@@ -1560,10 +1477,10 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
     //     2X2 transform of DC coeffs.
     run=-1;
     scan_pos=0;    
-    m1[0]=curr_res[0][0];
-    m1[1]=curr_res[0][4];
-    m1[2]=curr_res[4][0];
-    m1[3]=curr_res[4][4];
+    m1[0] = mb_rres[0][0] = mb_ores[0][0];
+    m1[1] = mb_rres[0][4] = mb_ores[0][4];
+    m1[2] = mb_rres[4][0] = mb_ores[4][0];
+    m1[3] = mb_rres[4][4] = mb_ores[4][4];
 
     for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
     {
@@ -1573,12 +1490,12 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
 
       if (level  != 0)
       {
-        if (params->symbol_mode == CAVLC && img->qp < 4)
+        if (params->symbol_mode == CAVLC)
           level = imin(level, CAVLC_LEVEL_LIMIT);
 
         currMB->cbp_blk |= 0xf0000 << (uv << 2) ;    // if one of the 2x2-DC levels is != 0 set the
         cr_cbp=imax(1, cr_cbp);                     // coded-bit all 4 4x4 blocks (bit 16-19 or 20-23)
-        DCcoded = 1;
+        nonzero = TRUE;
         level = isignab(level, m1[coeff_ctr]);
         DCLevel[scan_pos  ] = level;
         DCRun  [scan_pos++] = run;
@@ -1597,7 +1514,10 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
     for (j=0; j < img->mb_cr_size_y; j+=BLOCK_SIZE)
     {
       for (i=0; i < img->mb_cr_size_x; i+=BLOCK_SIZE)
-        m3[i>>2][j>>2]= curr_res[j][i];
+      {
+        m3[i>>2][j>>2] = mb_ores[j][i];
+        mb_rres[j][i]  = mb_ores[j][i];
+      }
     }
 
 
@@ -1620,7 +1540,7 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
         //YUV422
         currMB->cbp_blk |= 0xff0000 << (uv << 3) ;   // if one of the DC levels is != 0 set the
         cr_cbp=imax(1,cr_cbp);                       // coded-bit all 4 4x4 blocks (bit 16-31 or 32-47) //YUV444
-        DCcoded = 1 ;
+        nonzero = TRUE;
 
         DCLevel[scan_pos  ] = isignab(level,M4[i][j]);
         DCRun  [scan_pos++] = run;
@@ -1656,7 +1576,8 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
 
         ++run;
 
-        level = iabs(curr_res[n2+j][n1+i]);
+        level = iabs(mb_ores[n2+j][n1+i]);
+        mb_rres[n2+j][n1+i] = mb_ores[n2+j][n1+i];
 
         if (img->AdaptiveRounding)
         {
@@ -1669,11 +1590,11 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
           coeff_cost += MAX_VALUE;                // set high cost, shall not be discarded
 
           cr_cbp_tmp=2;
-          ACLevel[scan_pos  ] = isignab(level,curr_res[n2+j][n1+i]);
+          ACLevel[scan_pos  ] = isignab(level, mb_ores[n2+j][n1+i]);
           ACRun  [scan_pos++] = run;
           run=-1;
 
-          level=isignab(level, curr_res[n2+j][n1+i]);
+          level = isignab(level, mb_ores[n2+j][n1+i]);          
         }
       }
       ACLevel[scan_pos] = 0;
@@ -1683,8 +1604,8 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
   for (j=0; j < img->mb_cr_size_y; j++)
   {      
     orig_img = &enc_picture->imgUV[uv][img->pix_c_y + j][img->pix_c_x];
-    m7 = curr_res[j];
-    pred_img = curr_mpr[j];
+    m7 = mb_rres[j];
+    pred_img = mb_pred[j];
     for (i=0; i < img->mb_cr_size_x; i++)
     {        
       orig_img[i] = (imgpel) m7[i] + pred_img[i];
@@ -1714,15 +1635,18 @@ int dct_chroma_ls(Macroblock *currMB, int uv, int cr_cbp)
 int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *coeff_cost, int intra)
 {
   int i,j,coeff_ctr;
-  int qp_const,ilev, level,scan_pos,run;
-  int nonzero;
+  int qp_const,ilev, level,scan_pos = 0,run = -1;
+  int nonzero = FALSE;
 
   imgpel **img_enc = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
   int c_err,qp_const2;
-  int qp_per,qp_rem, q_bits;
-  int qp_per_sp,qp_rem_sp,q_bits_sp;
+
+  int   qp = currMB->qp_scaled[pl]; 
+  int   qp_sp = (currMB->qpsp);
+
   const byte *c_cost = COEFF_COST4x4[params->disthres];
   const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
 
@@ -1737,39 +1661,43 @@ int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
   int c_err1, c_err2, level1, level2;
   double D_dis1, D_dis2;
   int len, info;
-  double lambda_mode   = 0.85 * pow (2, (currMB->qp - SHIFT_QP)/3.0) * 4;
+  double lambda_mode   = 0.85 * pow (2, (qp - SHIFT_QP)/3.0) * 4;
 
-  qp_per    = qp_per_matrix[(currMB->qp - MIN_QP)];
-  qp_rem    = qp_rem_matrix[(currMB->qp - MIN_QP)];
-  q_bits    = Q_BITS + qp_per;
-  qp_per_sp = qp_per_matrix[(currMB->qpsp - MIN_QP)];
-  qp_rem_sp = qp_rem_matrix[(currMB->qpsp - MIN_QP)];
-  q_bits_sp = Q_BITS + qp_per_sp;
+  int qp_per    = qp_per_matrix[qp];
+  int qp_rem    = qp_rem_matrix[qp];
+  int q_bits    = Q_BITS + qp_per;
+  int qp_per_sp = qp_per_matrix[qp_sp];
+  int qp_rem_sp = qp_rem_matrix[qp_sp];
+  int q_bits_sp = Q_BITS + qp_per_sp;
+
+  levelscale    = LevelScale4x4Comp[pl][intra][qp_rem];
+  invlevelscale = InvLevelScale4x4Comp[pl][intra][qp_rem];
+  leveloffset   = ptLevelOffset4x4[intra][qp];
+
+  levelscale_sp    = LevelScale4x4Comp[pl][intra][qp_rem_sp];
+  invlevelscale_sp = InvLevelScale4x4Comp[pl][intra][qp_rem_sp];
+  leveloffset_sp   = ptLevelOffset4x4[intra][qp_sp];
 
   qp_const  = (1<<q_bits)/6;    // inter
   qp_const2 = (1<<q_bits_sp)/2;  //sp_pred
 
   //  Horizontal transform
-  for (j=0; j< BLOCK_SIZE; j++)
-    for (i=0; i< BLOCK_SIZE; i++)
-    {      
-      curr_res[j][i]+=curr_mpr[j+block_y][i+block_x];
-      M1[j][i]=curr_mpr[j+block_y][i+block_x];
+  for (j=block_y; j< block_x + BLOCK_SIZE; j++)
+  {
+    for (i=block_x; i< block_x + BLOCK_SIZE; i++)
+    { 
+      mb_rres[j][i] = mb_ores[j][i];
+      mb_rres[j][i]+=mb_pred[j][i];
+      M1[j][i] = mb_pred[j][i];
     }
+  }
 
-    
-  forward4x4(curr_res, curr_res, 0, 0);
-  forward4x4(M1, M1, 0, 0);
-
-  // Quant
-  nonzero=FALSE;
+  // 4x4 transform
+  forward4x4(mb_rres, mb_rres, block_y, block_x);
+  forward4x4(M1, M1, block_y, block_x);
 
-  run=-1;
-  scan_pos=0;
-
-  for (coeff_ctr=0;coeff_ctr < 16;coeff_ctr++)     // 8 times if double scan, 16 normal scan
+  for (coeff_ctr = 0;coeff_ctr < 16;coeff_ctr++)     
   {
-
     i = pos_scan[coeff_ctr][0];
     j = pos_scan[coeff_ctr][1];
 
@@ -1779,35 +1707,33 @@ int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
     // decide prediction
 
     // case 1
-    level1 = (iabs (M1[j][i]) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp;
-    level1 = (level1 << q_bits_sp) / quant_coef[qp_rem_sp][j][i];
-    c_err1 = curr_res[j][i]-isignab(level1, M1[j][i]);
-    level1 = (iabs (c_err1) * quant_coef[qp_rem][j][i] + qp_const) >> q_bits;
+    level1 = (iabs (M1[j][i]) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp;
+    level1 = (level1 << q_bits_sp) / levelscale_sp[j][i];
+    c_err1 = mb_rres[j][i] - isignab(level1, M1[j][i]);
+    level1 = (iabs (c_err1) * levelscale[j][i] + qp_const) >> q_bits;
 
     // case 2
-    c_err2=curr_res[j][i]-M1[j][i];
-    level2 = (iabs (c_err2) * quant_coef[qp_rem][j][i] + qp_const) >> q_bits;
+    c_err2 = mb_rres[j][i] - M1[j][i];
+    level2 = (iabs (c_err2) * levelscale[j][i] + qp_const) >> q_bits;
 
     // select prediction
     if ((level1 != level2) && (level1 != 0) && (level2 != 0))
     {
-      D_dis1 = curr_res[j][i] - ((isignab(level1,c_err1)*dequant_coef[qp_rem][j][i]*A[j][i]<< qp_per) >>6) - M1[j][i];
+      D_dis1 = mb_rres[j][i] - ((isignab(level1,c_err1) * invlevelscale[j][i] * A[j][i]<< qp_per) >>6) - M1[j][i];
       levrun_linfo_inter(level1, run, &len, &info);
-      D_dis1 = D_dis1*D_dis1 + lambda_mode * len;
+      D_dis1 = D_dis1 * D_dis1 + lambda_mode * len;
 
-      D_dis2 = curr_res[j][i] - ((isignab(level2,c_err2)*dequant_coef[qp_rem][j][i]*A[j][i]<< qp_per) >>6) - M1[j][i];
+      D_dis2 = mb_rres[j][i] - ((isignab(level2,c_err2)*invlevelscale[j][i] * A[j][i]<< qp_per) >>6) - M1[j][i];
       levrun_linfo_inter(level2, run, &len, &info);
       D_dis2 = D_dis2 * D_dis2 + lambda_mode * len;
 
       if (D_dis1 == D_dis2)
         level = (iabs(level1) < iabs(level2)) ? level1 : level2;
+      else if (D_dis1 < D_dis2)
+        level = level1;
       else
-      {
-        if (D_dis1 < D_dis2)
-          level = level1;
-        else
-          level = level2;
-      }
+        level = level2;
+
       c_err = (level == level1) ? c_err1 : c_err2;
     }
     else if (level1 == level2)
@@ -1824,7 +1750,7 @@ int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
     if (level != 0)
     {
       nonzero = TRUE;
-            
+
       *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
 
       level = isignab(level,c_err);
@@ -1832,32 +1758,41 @@ int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
       ACRun  [scan_pos] = run;
       ++scan_pos;
       run=-1;                     // reset zero level counter
-      ilev=((level * dequant_coef[qp_rem][j][i] * A[j][i] << qp_per) >>6);
+      ilev=((level * invlevelscale[j][i] * A[j][i] << qp_per) >>6);
     }
-    ilev+=M1[j][i];
-    
+
+    ilev += M1[j][i];
+
     if(!si_frame_indicator && !sp2_frame_indicator)//stores the SP frame coefficients in lrec, will be useful to encode these and create SI or SP switching frame
     {
       lrec[img->pix_y+block_y+j][img->pix_x+block_x+i]=
-        isignab((iabs(ilev) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp, ilev);
+        isignab((iabs(ilev) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp, ilev);
     }    
-    curr_res[j][i] = isignab((iabs(ilev) * quant_coef[qp_rem_sp][j][i] + qp_const2)>> q_bits_sp, ilev) * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+    mb_rres[j][i] = isignab((iabs(ilev) * levelscale_sp[j][i] + qp_const2)>> q_bits_sp, ilev) * invlevelscale_sp[j][i] << qp_per_sp;
   }
   ACLevel[scan_pos] = 0;
 
   // inverse transform
-  inverse4x4(curr_res, curr_res, 0, 0);
+  // inverse4x4(mb_rres, mb_rres, block_y, block_x);
+  inverse4x4(M1, mb_rres, 0, 0);
 
   for (j=0; j < BLOCK_SIZE; j++)
     for (i=0; i < BLOCK_SIZE; i++)
-      curr_res[j][i] = iClip1 (img->max_imgpel_value,rshift_rnd_sf(curr_res[j][i], DQ_BITS));
+    {
+      //printf("%d ",mb_rres[j][i]);
+      mb_rres[j][i] = iClip1 (img->max_imgpel_value, rshift_rnd_sf(mb_rres[j][i], DQ_BITS));
+       //printf("%d\n",mb_rres[j][i]);
+    }
 
   //  Decoded block moved to frame memory
-
   for (j=0; j < BLOCK_SIZE; j++)
-  for (i=0; i < BLOCK_SIZE; i++)
-    img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i]= (imgpel) curr_res[j][i];
-
+  {
+    for (i=0; i < BLOCK_SIZE; i++)
+    {
+      img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i]= (imgpel) mb_rres[j][i];
+  //printf("%d\n",mb_rres[j][i]);
+    }
+  }
   return nonzero;
 }
 
@@ -1879,16 +1814,222 @@ int dct_4x4_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *c
  */
 int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
 {
-  int i,j,ilev,n2,n1,coeff_ctr,qp_const,c_err,level ,scan_pos,run;
+  int i, j, n2, n1, coeff_ctr;
+  static int m1[BLOCK_SIZE];
+  int coeff_cost = 0;
+  int cr_cbp_tmp = 0;
+  int DCzero = FALSE;
+  int nonzero[4][4] = {{FALSE}};
+  int nonezero = FALSE;
+
+  const byte *c_cost = COEFF_COST4x4[params->disthres];
+
+  int   b4;
+  int*  DCLevel = img->cofDC[uv+1][0];
+  int*  DCRun   = img->cofDC[uv+1][1];
+  int*  ACLevel;
+  int*  ACRun;
+  int   intra = IS_INTRA (currMB);
+  int   uv_scale = uv * (img->num_blk8x8_uv >> 1);
+
+  //FRExt
+  static const int64 cbpblk_pattern[4]={0, 0xf0000, 0xff0000, 0xffff0000};
+  int yuv = img->yuv_format;
+  int b8;  
+
+  const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
+  int cur_qp = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;  
+
+  int qp_rem = qp_rem_matrix[cur_qp];
+
+  int max_imgpel_value_uv = img->max_imgpel_value_comp[uv + 1];
+
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 
+
+  levelscale    = LevelScale4x4Comp   [uv + 1][intra][qp_rem];
+  leveloffset   = LevelOffset4x4Comp  [uv + 1][intra][cur_qp];
+  invlevelscale = InvLevelScale4x4Comp[uv + 1][intra][qp_rem];
+  fadjust4x4    = img->AdaptiveRounding ? img->fadjust4x4Cr[intra][uv] : NULL;
+
+  //============= dct transform ===============
+  for (n2=0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
+  {
+    for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
+    {
+      forward4x4(mb_ores, mb_rres, n2, n1);
+    }
+  }
+
+  if (yuv == YUV420)
+  {
+    //================== CHROMA DC YUV420 ===================
+  
+    // forward 2x2 hadamard
+    hadamard2x2(mb_rres, m1);
+
+    // Quantization process of chroma 2X2 hadamard transformed DC coeffs.
+    DCzero = quant_dc_cr(&m1, cur_qp, DCLevel, DCRun, fadjust2x2, levelscale[0][0], invlevelscale[0][0], leveloffset, pos_scan);
+
+    if (DCzero) 
+    {
+        currMB->cbp_blk |= 0xf0000 << (uv << 2) ;    // if one of the 2x2-DC levels is != 0 set the
+        cr_cbp=imax(1,cr_cbp);                     // coded-bit all 4 4x4 blocks (bit 16-19 or 20-23)
+    }
+
+    //  Inverse transform of 2x2 DC levels
+    ihadamard2x2(m1, m1);
+
+    mb_rres[0][0] = m1[0];
+    mb_rres[0][4] = m1[1];
+    mb_rres[4][0] = m1[2];
+    mb_rres[4][4] = m1[3];
+  }
+  else if (yuv == YUV422)
+  {
+    //for YUV422 only
+    int cur_qp_dc = currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale;
+    int qp_rem_dc = qp_rem_matrix[cur_qp_dc];
+
+    invlevelscaleDC = InvLevelScale4x4Comp[uv + 1][intra][qp_rem_dc];
+    levelscaleDC    = LevelScale4x4Comp   [uv + 1][intra][qp_rem_dc];
+    leveloffsetDC   = LevelOffset4x4Comp  [uv + 1][intra][cur_qp_dc];
+
+    //================== CHROMA DC YUV422 ===================
+    //pick out DC coeff    
+    for (j=0; j < img->mb_cr_size_y; j+=BLOCK_SIZE)
+    {
+      for (i=0; i < img->mb_cr_size_x; i+=BLOCK_SIZE)
+        M4[i>>2][j>>2]= mb_rres[j][i];
+    }
+
+    // forward hadamard transform. Note that coeffs have been transposed (4x2 instead of 2x4) which makes transform a bit faster
+    hadamard4x2(M4, M4);
+
+    // Quantization process of chroma transformed DC coeffs.
+    DCzero = quant_dc_cr(M4, cur_qp_dc, DCLevel, DCRun, fadjust4x2, levelscaleDC[0][0], invlevelscaleDC[0][0], leveloffsetDC, SCAN_YUV422);
+
+    if (DCzero)
+    {
+      currMB->cbp_blk |= 0xff0000 << (uv << 3) ;   // if one of the DC levels is != 0 set the
+      cr_cbp=imax(1,cr_cbp);                       // coded-bit all 4 4x4 blocks (bit 16-31 or 32-47) //YUV444
+    }
+
+    //inverse DC transform. Note that now M4 is transposed back
+    ihadamard4x2(M4, M4);    
+
+    // This code assumes sizeof(int) > 16. Therefore, no need to have conditional
+    for (j = 0; j < 4; j++)
+    {
+      mb_rres[j << 2 ][0] = M4[j][0];
+      mb_rres[j << 2 ][4] = M4[j][1];
+    }
+  }
+
+  //     Quant of chroma AC-coeffs.
+  for (b8=0; b8 < (img->num_blk8x8_uv >> 1); b8++)
+  {
+    for (b4=0; b4 < 4; b4++)
+    {
+      int64 uv_cbpblk = ((int64)1) << cbp_blk_chroma[b8 + uv_scale][b4];      
+      n1 = hor_offset[yuv][b8][b4];
+      n2 = ver_offset[yuv][b8][b4];
+      ACLevel = img->cofAC[4 + b8 + uv_scale][b4][0];
+      ACRun   = img->cofAC[4 + b8 + uv_scale][b4][1];
+
+      // Quantization process
+      nonzero[n2>>2][n1>>2] = quant_ac4x4cr(&mb_rres[n2], n2, n1, cur_qp, ACLevel, ACRun, &fadjust4x4[n2], 
+        levelscale, invlevelscale, leveloffset, &coeff_cost, pos_scan, c_cost, CHROMA_AC);
+
+      if (nonzero[n2>>2][n1>>2])
+      {
+        currMB->cbp_blk |= uv_cbpblk;
+        cr_cbp_tmp = 2;
+        nonezero = TRUE;
+      }
+    }
+  }
+
+  // Perform thresholding
+  // * reset chroma coeffs
+  if(nonezero && coeff_cost < _CHROMA_COEFF_COST_)
+  {
+    int64 uv_cbpblk = ((int64)cbpblk_pattern[yuv] << (uv << (1+yuv)));
+    cr_cbp_tmp = 0;
+
+    for (b8 = 0; b8 < (img->num_blk8x8_uv >> 1); b8++)
+    {
+      for (b4 = 0; b4 < 4; b4++)
+      {
+        n1 = hor_offset[yuv][b8][b4];
+        n2 = ver_offset[yuv][b8][b4];
+        if (nonzero[n2>>2][n1>>2] == TRUE)
+        {
+          nonzero[n2>>2][n1>>2] = FALSE;
+          ACLevel = img->cofAC[4 + b8 + uv_scale][b4][0];
+          ACRun   = img->cofAC[4 + b8 + uv_scale][b4][1];
+
+          if (DCzero == 0)
+            currMB->cbp_blk &= ~(uv_cbpblk);  // if no chroma DC's: then reset coded-bits of this chroma subblock
+
+          ACLevel[0] = 0;
+
+          for (coeff_ctr=1; coeff_ctr < 16; coeff_ctr++)// ac coeff
+          {
+            mb_rres[n2 + pos_scan[coeff_ctr][1]][n1 + pos_scan[coeff_ctr][0]] = 0;
+            ACLevel[coeff_ctr]  = 0;
+          }
+        }
+      }
+    }
+  }
+
+  //     IDCT.
+  //     Horizontal.
+  if(cr_cbp_tmp == 2)
+    cr_cbp = 2;
+
+  nonezero = FALSE;
+  for (n2=0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
+  {
+    for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
+    {
+      if (mb_rres[n2][n1] != 0 || nonzero[n2>>2][n1>>2] == TRUE)
+      {
+        inverse4x4(mb_rres, mb_rres, n2, n1);
+        nonezero = TRUE;
+      }
+    }
+  }
+
+  //  Decoded block moved to memory
+  if (nonezero == TRUE)
+  {
+    SampleReconstruct (enc_picture->imgUV[uv], mb_pred, mb_rres, 0, 0, img->pix_c_y, img->pix_c_x, img->mb_cr_size_x, img->mb_cr_size_y, max_imgpel_value_uv, DQ_BITS);
+  }
+  else
+  {
+    for (j=0; j < img->mb_cr_size_y; j++)
+    {
+      memcpy(&enc_picture->imgUV[uv][img->pix_c_y + j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
+    }
+  }
+
+  return cr_cbp;
+}
+
+int dct_chroma_sp_old(Macroblock *currMB, int uv,int cr_cbp)
+{
+  int i,j,ilev,n2,n1,coeff_ctr,c_err,level ,scan_pos,run;
   int m1[BLOCK_SIZE];
   int coeff_cost;
   int cr_cbp_tmp;
-  int qp_const2,mp1[BLOCK_SIZE];
+  int mp1[BLOCK_SIZE];
   const byte *c_cost = COEFF_COST4x4[params->disthres];
   const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
 
-  int qp_per, qp_rem, q_bits;
-  int qp_per_sp, qp_rem_sp, q_bits_sp;
+  int   intra = IS_INTRA (currMB);
 
   int   b4;
   int*  DCLevel = img->cofDC[uv+1][0];
@@ -1902,28 +2043,36 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
   double lambda_mode   = 0.85 * pow (2, (currMB->qp -SHIFT_QP)/3.0) * 4;
   int max_imgpel_value_uv = img->max_imgpel_value_comp[1];
 
-
-  int qpChroma = iClip3(-img->bitdepth_chroma_qp_scale, 51, currMB->qp + active_pps->chroma_qp_index_offset);
+  int qpChroma = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;   
   int qpChromaSP=iClip3(-img->bitdepth_chroma_qp_scale, 51, currMB->qpsp + active_pps->chroma_qp_index_offset);
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[uv + 1]; 
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[uv + 1]; 
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 
+
+  int qp_per    = qp_per_matrix[qpChroma];
+  int qp_rem    = qp_rem_matrix[qpChroma];
+  int q_bits    = Q_BITS + qp_per;
+  int qp_const  = (1<<q_bits)/6;    // inter
+  int qp_per_sp = qp_per_matrix[qpChromaSP];
+  int qp_rem_sp = qp_rem_matrix[qpChromaSP];
+  int q_bits_sp = Q_BITS + qp_per_sp;
+  int qp_const2 = (1<<q_bits_sp)/2;  //sp_pred
 
-  qp_per    = ((qpChroma<0?qpChroma:QP_SCALE_CR[qpChroma])-MIN_QP)/6;
-  qp_rem    = ((qpChroma<0?qpChroma:QP_SCALE_CR[qpChroma])-MIN_QP)%6;
-  q_bits    = Q_BITS+qp_per;
-  qp_const=(1<<q_bits)/6;    // inter
-  qp_per_sp    = ((qpChromaSP<0?currMB->qpsp:QP_SCALE_CR[qpChromaSP])-MIN_QP)/6;
-  qp_rem_sp    = ((qpChromaSP<0?currMB->qpsp:QP_SCALE_CR[qpChromaSP])-MIN_QP)%6;
-  q_bits_sp    = Q_BITS+qp_per_sp;
-  qp_const2 = (1<<q_bits_sp)/2;  //sp_pred
+  levelscale    = LevelScale4x4Comp   [uv + 1][intra][qp_rem];
+  invlevelscale = InvLevelScale4x4Comp[uv + 1][intra][qp_rem];
+  leveloffset   = LevelOffset4x4Comp  [uv + 1][intra][qpChroma];
 
+  levelscale_sp    = LevelScale4x4Comp   [uv + 1][intra][qp_rem_sp];
+  invlevelscale_sp = InvLevelScale4x4Comp[uv + 1][intra][qp_rem_sp];
+  leveloffset_sp   = LevelOffset4x4Comp  [uv + 1][intra][qpChromaSP];
 
   for (j=0; j < img->mb_cr_size_y; j++)
   {
     for (i=0; i < img->mb_cr_size_x; i++)
     {
-      curr_res[j][i] += curr_mpr[j][i];
-      M1[j][i] = curr_mpr[j][i];
+      mb_rres[j][i]  = mb_ores[j][i];
+      mb_rres[j][i] += mb_pred[j][i];
+      M1[j][i] = mb_pred[j][i];
     }
   }
   
@@ -1931,52 +2080,50 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
   {
     for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
     {
-      forward4x4(curr_res, curr_res, n2, n1);      
+      forward4x4(mb_rres, mb_rres, n2, n1);      
       forward4x4(M1, M1, n2, n1);
     }
   }
 
   //     2X2 transform of DC coeffs.
-  hadamard2x2(curr_res, m1);
+  hadamard2x2(mb_rres, m1);
   hadamard2x2(M1, mp1);
 
   run=-1;
   scan_pos=0;
 
-  for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
+  for (coeff_ctr = 0; coeff_ctr < 4; coeff_ctr++)
   {
     run++;
     ilev=0;
 
     // case 1
-    c_err1 = (iabs (mp1[coeff_ctr]) * quant_coef[qp_rem_sp][0][0] + 2 * qp_const2) >> (q_bits_sp + 1);
-    c_err1 = (c_err1 << (q_bits_sp + 1)) / quant_coef[qp_rem_sp][0][0];
+    c_err1 = (iabs (mp1[coeff_ctr]) * levelscale_sp[0][0] + 2 * qp_const2) >> (q_bits_sp + 1);
+    c_err1 = (c_err1 << (q_bits_sp + 1)) / levelscale_sp[0][0];
     c_err1 = m1[coeff_ctr] - isignab(c_err1, mp1[coeff_ctr]);
-    level1 = (iabs(c_err1) * quant_coef[qp_rem][0][0] + 2 * qp_const) >> (q_bits+1);
+    level1 = (iabs(c_err1) * levelscale[0][0] + 2 * qp_const) >> (q_bits+1);
 
     // case 2
     c_err2 = m1[coeff_ctr] - mp1[coeff_ctr];
-    level2 = (iabs(c_err2) * quant_coef[qp_rem][0][0] + 2 * qp_const) >> (q_bits+1);
+    level2 = (iabs(c_err2) * levelscale[0][0] + 2 * qp_const) >> (q_bits+1);
 
     if (level1 != level2 && level1 != 0 && level2 != 0)
     {
-      D_dis1 = m1[coeff_ctr] - ((isignab(level1,c_err1)*dequant_coef[qp_rem][0][0]*A[0][0]<< qp_per) >>5)- mp1[coeff_ctr];
+      D_dis1 = m1[coeff_ctr] - ((isignab(level1,c_err1)*invlevelscale[0][0] * A[0][0]<< qp_per) >>5)- mp1[coeff_ctr];
       levrun_linfo_c2x2(level1, run, &len, &info);
       D_dis1 = D_dis1 * D_dis1 + lambda_mode * len;
 
-      D_dis2 = m1[coeff_ctr] - ((isignab(level2,c_err2)*dequant_coef[qp_rem][0][0]*A[0][0]<< qp_per) >>5)- mp1[coeff_ctr];
+      D_dis2 = m1[coeff_ctr] - ((isignab(level2,c_err2)*invlevelscale[0][0] * A[0][0]<< qp_per) >>5)- mp1[coeff_ctr];
       levrun_linfo_c2x2(level2, run, &len, &info);
       D_dis2 = D_dis2 * D_dis2 + lambda_mode * len;
 
       if (D_dis1 == D_dis2)
         level = (iabs(level1) < iabs(level2)) ? level1 : level2;
+      else if (D_dis1 < D_dis2)
+        level = level1;
       else
-      {
-        if (D_dis1 < D_dis2)
-          level = level1;
-        else
-          level = level2;
-      }
+        level = level2;
+
       c_err = (level == level1) ? c_err1 : c_err2;
     }
     else if (level1 == level2)
@@ -1992,30 +2139,31 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
 
     if (level  != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 4)
+      if (params->symbol_mode == CAVLC)
         level = imin(level, CAVLC_LEVEL_LIMIT);
       
       currMB->cbp_blk |= 0xf0000 << (uv << 2) ;  // if one of the 2x2-DC levels is != 0 the coded-bit
-      cr_cbp=imax(1,cr_cbp);
+      cr_cbp = imax(1, cr_cbp);
       DCLevel[scan_pos  ] = isignab(level ,c_err);
       DCRun  [scan_pos++] = run;
       run=-1;
-      ilev=((isignab(level,c_err)*dequant_coef[qp_rem][0][0]*A[0][0]<< qp_per) >>5);
+      ilev=((isignab(level,c_err)*invlevelscale[0][0]*A[0][0]<< qp_per) >>5);
     }
+
     ilev+= mp1[coeff_ctr];
-    m1[coeff_ctr]=isignab((iabs(ilev)  * quant_coef[qp_rem_sp][0][0] + 2 * qp_const2) >> (q_bits_sp+1), ilev) * dequant_coef[qp_rem_sp][0][0] << qp_per_sp;
+    m1[coeff_ctr]=isignab((iabs(ilev)  * levelscale_sp[0][0] + 2 * qp_const2) >> (q_bits_sp+1), ilev) * invlevelscale_sp[0][0] << qp_per_sp;
     if(!si_frame_indicator && !sp2_frame_indicator)
-      lrec_uv[uv][img->pix_c_y+4*(coeff_ctr%2)][img->pix_c_x+4*(coeff_ctr/2)]=isignab((iabs(ilev)  * quant_coef[qp_rem_sp][0][0] + 2 * qp_const2) >> (q_bits_sp+1), ilev);// stores the SP frames coefficients, will be useful to encode SI or switching SP frame
+      lrec_uv[uv][img->pix_c_y+4*(coeff_ctr%2)][img->pix_c_x+4*(coeff_ctr/2)]=isignab((iabs(ilev)  * levelscale_sp[0][0] + 2 * qp_const2) >> (q_bits_sp+1), ilev);// stores the SP frames coefficients, will be useful to encode SI or switching SP frame
   }
   DCLevel[scan_pos] = 0;
 
   //  Inverse transform of 2x2 DC levels
   ihadamard2x2(m1, m1);
 
-  curr_res[0][0]=(m1[0])>>1;
-  curr_res[0][4]=(m1[1])>>1;
-  curr_res[4][0]=(m1[2])>>1;
-  curr_res[4][4]=(m1[3])>>1;
+  mb_rres[0][0]=(m1[0])>>1;
+  mb_rres[0][4]=(m1[1])>>1;
+  mb_rres[4][0]=(m1[2])>>1;
+  mb_rres[4][4]=(m1[3])>>1;
 
   //     Quant of chroma AC-coeffs.
   coeff_cost=0;
@@ -2041,23 +2189,23 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
         ilev=0;
 
         // quantization on prediction
-        c_err1 = (iabs(M1[n2+j][n1+i]) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp;
-        c_err1 = (c_err1 << q_bits_sp) / quant_coef[qp_rem_sp][j][i];
-        c_err1 = curr_res[n2+j][n1+i] - isignab(c_err1, M1[n2+j][n1+i]);
-        level1 = (iabs(c_err1) * quant_coef[qp_rem][j][i] + qp_const) >> q_bits;
+        c_err1 = (iabs(M1[n2+j][n1+i]) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp;
+        c_err1 = (c_err1 << q_bits_sp) / levelscale_sp[j][i];
+        c_err1 = mb_rres[n2+j][n1+i] - isignab(c_err1, M1[n2+j][n1+i]);
+        level1 = (iabs(c_err1) * levelscale[j][i] + qp_const) >> q_bits;
 
         // no quantization on prediction
-        c_err2 = curr_res[n2+j][n1+i] - M1[n2+j][n1+i];
-        level2 = (iabs(c_err2) * quant_coef[qp_rem][j][i] + qp_const) >> q_bits;
+        c_err2 = mb_rres[n2+j][n1+i] - M1[n2+j][n1+i];
+        level2 = (iabs(c_err2) * levelscale[j][i] + qp_const) >> q_bits;
 
         if (level1 != level2 && level1 != 0 && level2 != 0)
         {
-          D_dis1 = curr_res[n2+j][n1+i] - ((isignab(level1,c_err1)*dequant_coef[qp_rem][j][i]*A[j][i]<< qp_per) >>6) - M1[n2+j][n1+i];
+          D_dis1 = mb_rres[n2+j][n1+i] - ((isignab(level1,c_err1)*invlevelscale[j][i]*A[j][i]<< qp_per) >>6) - M1[n2+j][n1+i];
 
           levrun_linfo_inter(level1, run, &len, &info);
           D_dis1 = D_dis1 * D_dis1 + lambda_mode * len;
 
-          D_dis2 = curr_res[n2+j][n1+i] - ((isignab(level2,c_err2)*dequant_coef[qp_rem][j][i]*A[j][i]<< qp_per) >>6) - M1[n2+j][n1+i];
+          D_dis2 = mb_rres[n2+j][n1+i] - ((isignab(level2,c_err2)*invlevelscale[j][i]*A[j][i]<< qp_per) >>6) - M1[n2+j][n1+i];
           levrun_linfo_inter(level2, run, &len, &info);
           D_dis2 = D_dis2 * D_dis2 + lambda_mode * len;
 
@@ -2095,13 +2243,13 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
           ACRun  [scan_pos] = run;
           ++scan_pos;
           run=-1;
-          ilev=((level * dequant_coef[qp_rem][j][i]*A[j][i]<< qp_per) >>6);
+          ilev=((level * invlevelscale[j][i]*A[j][i]<< qp_per) >>6);
         }
         ilev+=M1[n2+j][n1+i];
         if(!si_frame_indicator && !sp2_frame_indicator)
           if(!( (n2+j) % 4==0 && (n1+i)%4 ==0 ))
-            lrec_uv[uv][img->pix_c_y+n1+j][img->pix_c_x+n2+i]=isignab((iabs(ilev) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp,ilev);//stores the SP frames coefficients, will be useful to encode SI or switching SP frame
-        curr_res[n2+j][n1+i] = isignab((iabs(ilev) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp,ilev) * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+            lrec_uv[uv][img->pix_c_y+n1+j][img->pix_c_x+n2+i]=isignab((iabs(ilev) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp,ilev);//stores the SP frames coefficients, will be useful to encode SI or switching SP frame
+        mb_rres[n2+j][n1+i] = isignab((iabs(ilev) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp,ilev) * invlevelscale_sp[j][i] << qp_per_sp;
       }
       ACLevel[scan_pos] = 0;
     }
@@ -2113,18 +2261,18 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
     cr_cbp=2;
   //     IDCT.
 
-      //     Horizontal.
+  //     Horizontal.
   for (n2=0; n2 <= BLOCK_SIZE; n2 += BLOCK_SIZE)
   {
     for (n1=0; n1 <= BLOCK_SIZE; n1 += BLOCK_SIZE)
     {
-      inverse4x4(curr_res, curr_res, n2, n1);
+      inverse4x4(mb_rres, mb_rres, n2, n1);
 
       for (j=0; j < BLOCK_SIZE; j++)
-      for (i=0; i < BLOCK_SIZE; i++)
-      {
-        curr_res[n2+j][n1+i] = iClip1 (max_imgpel_value_uv,rshift_rnd_sf(curr_res[n2+j][n1+i], DQ_BITS));
-      }
+        for (i=0; i < BLOCK_SIZE; i++)
+        {
+          mb_rres[n2+j][n1+i] = iClip1 (max_imgpel_value_uv,rshift_rnd_sf(mb_rres[n2+j][n1+i], DQ_BITS));
+        }
     }
   }
 
@@ -2132,10 +2280,10 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
   for (j=0; j < BLOCK_SIZE*2; j++)
     for (i=0; i < BLOCK_SIZE*2; i++)
     {
-      enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x+i]= (imgpel) curr_res[j][i];
+      enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x+i]= (imgpel) mb_rres[j][i];
     }
 
-  return cr_cbp;
+    return cr_cbp;
 }
 
 /*!
@@ -2155,109 +2303,61 @@ int dct_chroma_sp(Macroblock *currMB, int uv,int cr_cbp)
  */
 void copyblock_sp(Macroblock *currMB, ColorPlane pl, int block_x,int block_y)
 {
-  int i,j,i1,j1,m5[4],m6[4];
+  int i, j;
 
-  int qp_per = (currMB->qpsp-MIN_QP)/6;
-  int qp_rem = (currMB->qpsp-MIN_QP)%6;
-  int q_bits    = Q_BITS+qp_per;
+  int cur_qp = currMB->qpsp + img->bitdepth_luma_qp_scale;  
+  int qp_per = qp_per_matrix[cur_qp];
+  int qp_rem = qp_rem_matrix[cur_qp];
+  int q_bits = Q_BITS + qp_per;
   int qp_const2=(1<<q_bits)/2;  //sp_pred
   imgpel **img_enc       = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl]; 
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl]; 
-  
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl]; 
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl]; 
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl]; 
+
+  levelscale    = LevelScale4x4Comp[pl][0][qp_rem];
+  invlevelscale = InvLevelScale4x4Comp[pl][0][qp_rem];
+  leveloffset   = ptLevelOffset4x4[0][cur_qp];
 
   //  Horizontal transform
   for (j=0; j< BLOCK_SIZE; j++)
-    for (i=0; i< BLOCK_SIZE; i++)
-    {
-      M1[i][j]=curr_mpr[j+block_y][i+block_x];
-    }
-
-  for (j=0; j < BLOCK_SIZE; j++)
   {
-    for (i=0; i < 2; i++)
+    for (i=0; i< BLOCK_SIZE; i++)
     {
-      i1=3-i;
-      m5[i]=M1[i][j]+M1[i1][j];
-      m5[i1]=M1[i][j]-M1[i1][j];
+      mb_rres[j+block_y][i+block_x] = mb_ores[j+block_y][i+block_x];
+      M1[i][j]=mb_pred[j+block_y][i+block_x];
     }
-    M1[0][j]=(m5[0]+m5[1]);
-    M1[2][j]=(m5[0]-m5[1]);
-    M1[1][j]=m5[3]*2+m5[2];
-    M1[3][j]=m5[3]-m5[2]*2;
   }
 
-  //  Vertical transform
-
-  for (i=0; i < BLOCK_SIZE; i++)
-  {
-    for (j=0; j < 2; j++)
-    {
-      j1=3-j;
-      m5[j]=M1[i][j]+M1[i][j1];
-      m5[j1]=M1[i][j]-M1[i][j1];
-    }
-    M1[i][0]=(m5[0]+m5[1]);
-    M1[i][2]=(m5[0]-m5[1]);
-    M1[i][1]=m5[3]*2+m5[2];
-    M1[i][3]=m5[3]-m5[2]*2;
-  }
+  forward4x4(M1, M1, 0, 0);
 
   // Quant
   for (j=0;j < BLOCK_SIZE; j++)
   {
     for (i=0; i < BLOCK_SIZE; i++)
     {
-      curr_res[j][i]=isignab((iabs(M1[i][j])* quant_coef[qp_rem][i][j]+qp_const2)>> q_bits,M1[i][j])*dequant_coef[qp_rem][i][j]<<qp_per;
+      mb_rres[j][i]=isignab((iabs(M1[i][j])* levelscale[i][j]+qp_const2)>> q_bits,M1[i][j])*levelscale[i][j]<<qp_per;
       if(!si_frame_indicator && !sp2_frame_indicator)
       {
         lrec[img->pix_y+block_y+j][img->pix_x+block_x+i] =
-        isignab((iabs(M1[i][j]) * quant_coef[qp_rem][i][j] + qp_const2) >> q_bits, M1[i][j]);// stores the SP frames coefficients, will be useful to encode SI or switching SP frame
+          isignab((iabs(M1[i][j]) * levelscale[i][j] + qp_const2) >> q_bits, M1[i][j]);// stores the SP frames coefficients, will be useful to encode SI or switching SP frame
       }
     }
   }
 
   //     IDCT.
   //     horizontal
+  inverse4x4(mb_rres, mb_rres, 0, 0);
 
-  for (j=0;j<BLOCK_SIZE;j++)
+  //  Decoded block moved to frame memory
+  for (j=0; j < BLOCK_SIZE; j++)
   {
-    for (i=0;i<BLOCK_SIZE;i++)
+    for (i=0; i < BLOCK_SIZE; i++)
     {
-      m5[i]=curr_res[j][i];
+      mb_rres[j][i] = iClip1 (img->max_imgpel_value, mb_rres[j][i]);
+      img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i]=(imgpel) mb_rres[j][i];
     }
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
-
-    curr_res[j][0]=m6[0]+m6[3];
-    curr_res[j][1]=m6[1]+m6[2];
-    curr_res[j][2]=m6[1]-m6[2];
-    curr_res[j][3]=m6[0]-m6[3];
   }
-  // vertical
-  for (i=0;i<BLOCK_SIZE;i++)
-  {
-    for (j=0;j<BLOCK_SIZE;j++)
-      m5[j]=curr_res[j][i];
-
-    m6[0]=(m5[0]+m5[2]);
-    m6[1]=(m5[0]-m5[2]);
-    m6[2]=(m5[1]>>1)-m5[3];
-    m6[3]=m5[1]+(m5[3]>>1);
-
-    curr_res[0][i] = iClip1 (img->max_imgpel_value,rshift_rnd_sf(m6[0]+m6[3], DQ_BITS));
-    curr_res[1][i] = iClip1 (img->max_imgpel_value,rshift_rnd_sf(m6[1]+m6[2], DQ_BITS));
-    curr_res[2][i] = iClip1 (img->max_imgpel_value,rshift_rnd_sf(m6[1]-m6[2], DQ_BITS));    
-    curr_res[3][i] = iClip1 (img->max_imgpel_value,rshift_rnd_sf(m6[0]-m6[3], DQ_BITS));
-  }
-
-  //  Decoded block moved to frame memory
-
-  for (j=0; j < BLOCK_SIZE; j++)
-    for (i=0; i < BLOCK_SIZE; i++)
-      img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i]=(imgpel) curr_res[j][i];
 }
 
 
@@ -2336,15 +2436,14 @@ int writePCMByteAlign(Bitstream *currStream)
 int dct_4x4_sp2(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *coeff_cost, int intra)
 {
   int i,j,ilev,coeff_ctr;
-  int qp_const,level,scan_pos,run;
-  int nonzero;
+  int qp_const,level,scan_pos = 0,run = -1;
+  int nonzero = FALSE;
 
   imgpel **img_enc = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];   
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl];   
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];   
+//  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];   
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];   
   int c_err,qp_const2;
-  int qp_per,qp_rem,q_bits;
-  int qp_per_sp,qp_rem_sp,q_bits_sp;
 
   int   pos_x   = block_x >> BLOCK_SHIFT;
   int   pos_y   = block_y >> BLOCK_SHIFT;
@@ -2357,34 +2456,40 @@ int dct_4x4_sp2(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *
 
   int level1;
 
-  qp_per    = (img->qpsp-MIN_QP)/6 ;
-  qp_rem    = (img->qpsp-MIN_QP)%6;
-  q_bits    = Q_BITS+qp_per;
-  qp_per_sp    = (img->qpsp-MIN_QP)/6;
-  qp_rem_sp    = (img->qpsp-MIN_QP)%6;
-  q_bits_sp    = Q_BITS+qp_per_sp;
+  int   qp    = (currMB->qpsp); // should double check spec why these are equal
+  int   qp_sp = (currMB->qpsp);
+
+  int qp_per    = qp_per_matrix[qp];
+  int qp_rem    = qp_rem_matrix[qp];
+  int q_bits    = Q_BITS + qp_per;
+  int qp_per_sp = qp_per_matrix[qp_sp];
+  int qp_rem_sp = qp_rem_matrix[qp_sp];
+  int q_bits_sp = Q_BITS + qp_per_sp;
+
+  levelscale    = LevelScale4x4Comp[pl][intra][qp_rem];
+  invlevelscale = InvLevelScale4x4Comp[pl][intra][qp_rem];
+  leveloffset   = ptLevelOffset4x4[intra][qp];
+
+  levelscale_sp    = LevelScale4x4Comp[pl][intra][qp_rem_sp];
+  invlevelscale_sp = InvLevelScale4x4Comp[pl][intra][qp_rem_sp];
+  leveloffset_sp   = ptLevelOffset4x4[intra][qp_sp];
 
   qp_const=(1<<q_bits)/6;    // inter
   qp_const2=(1<<q_bits_sp)/2;  //sp_pred
 
   for (j=0; j< BLOCK_SIZE; j++)
+  {
     for (i=0; i< BLOCK_SIZE; i++)
     {
       //Coefficients obtained from the prior encoding of the SP frame
-      curr_res[j][i]=lrec[img->pix_y+block_y+j][img->pix_x+block_x+i];
+      mb_rres[j][i] = lrec[img->pix_y+block_y+j][img->pix_x+block_x+i];
       //Predicted block
-      M1[j][i]=curr_mpr[j+block_y][i+block_x];
+      M1[j][i]=mb_pred[j+block_y][i+block_x];
     }
-
+  }
   // forward transform
   forward4x4(M1, M1, 0, 0);
 
-  // Quant
-  nonzero=FALSE;
-
-  run=-1;
-  scan_pos=0;
-
   for (coeff_ctr=0;coeff_ctr < 16;coeff_ctr++)     // 8 times if double scan, 16 normal scan
   {
 
@@ -2395,9 +2500,9 @@ int dct_4x4_sp2(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *
     ilev=0;
 
     //quantization of the predicted block
-    level1 = (iabs (M1[j][i]) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp;
+    level1 = (iabs (M1[j][i]) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp;
     //substracted from lrec
-    c_err = curr_res[j][i]-isignab(level1, M1[j][i]);   //substracting the predicted block
+    c_err = mb_rres[j][i]-isignab(level1, M1[j][i]);   //substracting the predicted block
 
     level = iabs(c_err);
     if (level != 0)
@@ -2413,17 +2518,17 @@ int dct_4x4_sp2(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *
     }
     //from now on we are in decoder land
     ilev=c_err + isignab(level1,M1[j][i]) ;  // adding the quantized predicted block
-    curr_res[j][i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+    mb_rres[j][i] = ilev * invlevelscale_sp[j][i] << qp_per_sp;
 
   }
   ACLevel[scan_pos] = 0;
 
   //  Inverse transform
-  inverse4x4(curr_res, curr_res, 0, 0);
+  inverse4x4(mb_rres, mb_rres, 0, 0);
 
   for (j=0; j < BLOCK_SIZE; j++)
     for (i=0; i < BLOCK_SIZE; i++)
-      img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i] =iClip3 (0, img->max_imgpel_value,rshift_rnd_sf(curr_res[j][i], DQ_BITS));
+      img_enc[img->pix_y+block_y+j][img->pix_x+block_x+i] =iClip3 (0, img->max_imgpel_value,rshift_rnd_sf(mb_rres[j][i], DQ_BITS));
 
   return nonzero;
 }
@@ -2450,44 +2555,54 @@ int dct_4x4_sp2(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *
  */
 int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
 {
-  int i,j,ilev,n2,n1,coeff_ctr,qp_const,c_err,level ,scan_pos,run;
+  int i,j,ilev,n2,n1,coeff_ctr,c_err,level ,scan_pos = 0,run = -1;
   int m1[BLOCK_SIZE];
   int coeff_cost;
   int cr_cbp_tmp;
-  int qp_const2,mp1[BLOCK_SIZE];
+  int mp1[BLOCK_SIZE];
   const byte *c_cost = COEFF_COST4x4[params->disthres];
   const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
 
-  int qp_per,qp_rem,q_bits;
-  int qp_per_sp,qp_rem_sp,q_bits_sp;
-
   int   b4;
   int*  DCLevel = img->cofDC[uv+1][0];
   int*  DCRun   = img->cofDC[uv+1][1];
   int*  ACLevel;
   int*  ACRun;
   int  level1;
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[uv + 1]; 
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[uv + 1]; 
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
+  //int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1]; 
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 
+  int   intra = IS_INTRA (currMB);
 
-  qp_per    = ((img->qp<0?img->qp:QP_SCALE_CR[img->qp])-MIN_QP)/6;
-  qp_rem    = ((img->qp<0?img->qp:QP_SCALE_CR[img->qp])-MIN_QP)%6;
-  q_bits    = Q_BITS+qp_per;
-  qp_const=(1<<q_bits)/6;    // inter
+  int qpChroma   = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;   
+  int qpChromaSP = iClip3(-img->bitdepth_chroma_qp_scale, 51, currMB->qpsp + active_pps->chroma_qp_index_offset);
+
+  int qp_per    = qp_per_matrix[qpChroma];
+  int qp_rem    = qp_rem_matrix[qpChroma];
 
-  qp_per_sp    = ((img->qpsp<0?img->qpsp:QP_SCALE_CR[img->qpsp])-MIN_QP)/6;
-  qp_rem_sp    = ((img->qpsp<0?img->qpsp:QP_SCALE_CR[img->qpsp])-MIN_QP)%6;
-  q_bits_sp    = Q_BITS+qp_per_sp;
-  qp_const2    = (1<<q_bits_sp)/2;  //sp_pred
+  int qp_per_sp = qp_per_matrix[qpChromaSP];
+  int qp_rem_sp = qp_rem_matrix[qpChromaSP];
+  int q_bits_sp = Q_BITS + qp_per;
+  int qp_const2 = (1 << q_bits_sp)/2;  //sp_pred
+
+  levelscale    = LevelScale4x4Comp[uv + 1][intra][qp_rem];
+  invlevelscale = InvLevelScale4x4Comp[uv + 1][intra][qp_rem];
+  leveloffset   = ptLevelOffset4x4[intra][qpChroma];
+
+  levelscale_sp    = LevelScale4x4Comp[uv + 1][intra][qp_rem_sp];
+  invlevelscale_sp = InvLevelScale4x4Comp[uv + 1][intra][qp_rem_sp];
+  leveloffset_sp   = ptLevelOffset4x4[intra][qpChromaSP];
 
   for (j=0; j < MB_BLOCK_SIZE>>1; j++)
+  {
     for (i=0; i < MB_BLOCK_SIZE>>1; i++)
     {
-      M1[j][i]=curr_mpr[j][i];
-      curr_res[j][i]=lrec_uv[uv][img->pix_c_y+j][img->pix_c_x+i];
+      M1[j][i]=mb_pred[j][i];
+      mb_rres[j][i]=lrec_uv[uv][img->pix_c_y+j][img->pix_c_x+i];
     }
+  }
+
 
-    
   for (n2=0; n2 <= BLOCK_SIZE; n2 += BLOCK_SIZE)
   {
     for (n1=0; n1 <= BLOCK_SIZE; n1 += BLOCK_SIZE)
@@ -2497,24 +2612,21 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
   }
 
   //   DC coefficients already transformed and quantized
-  m1[0]= curr_res[0][0];
-  m1[1]= curr_res[0][4];
-  m1[2]= curr_res[4][0];
-  m1[3]= curr_res[4][4];
+  m1[0]= mb_rres[0][0];
+  m1[1]= mb_rres[0][4];
+  m1[2]= mb_rres[4][0];
+  m1[3]= mb_rres[4][4];
 
   //     2X2 transform of predicted DC coeffs.
   hadamard2x2(M1, mp1);
 
-  run=-1;
-  scan_pos=0;
-
   for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
   {
     run++;
     ilev=0;
 
     //quantization of predicted DC coeff
-    level1 = (iabs (mp1[coeff_ctr]) * quant_coef[qp_rem_sp][0][0] + 2 * qp_const2) >> (q_bits_sp + 1);
+    level1 = (iabs (mp1[coeff_ctr]) * levelscale_sp[0][0] + 2 * qp_const2) >> (q_bits_sp + 1);
     //substratcted from lrecUV
     c_err = m1[coeff_ctr] - isignab(level1, mp1[coeff_ctr]);
     level = iabs(c_err);
@@ -2532,18 +2644,18 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
     //from now on decoder world
     ilev = c_err + isignab(level1,mp1[coeff_ctr]) ; // we have perfect reconstruction here
 
-    m1[coeff_ctr]= ilev  * dequant_coef[qp_rem_sp][0][0] << qp_per_sp;
+    m1[coeff_ctr]= ilev  * invlevelscale_sp[0][0] << qp_per_sp;
 
   }
   DCLevel[scan_pos] = 0;
 
-  //  Invers transform of 2x2 DC levels
+  //  Inverse transform of 2x2 DC levels
   ihadamard2x2(m1, m1);
 
-  curr_res[0][0]=m1[0]/2;
-  curr_res[0][4]=m1[1]/2;
-  curr_res[4][0]=m1[2]/2;
-  curr_res[4][4]=m1[3]/2;
+  mb_rres[0][0]=m1[0]/2;
+  mb_rres[0][4]=m1[1]/2;
+  mb_rres[4][0]=m1[2]/2;
+  mb_rres[4][4]=m1[3]/2;
 
   //     Quant of chroma AC-coeffs.
   coeff_cost=0;
@@ -2569,9 +2681,9 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
         ++run;
         ilev=0;
         // quantization on prediction
-        level1 = (iabs(M1[n2+j][n1+i]) * quant_coef[qp_rem_sp][j][i] + qp_const2) >> q_bits_sp;
+        level1 = (iabs(M1[n2+j][n1+i]) * levelscale_sp[j][i] + qp_const2) >> q_bits_sp;
         //substracted from lrec
-        c_err  = curr_res[n2+j][n1+i] - isignab(level1, M1[n2+j][n1+i]);
+        c_err  = mb_rres[n2+j][n1+i] - isignab(level1, M1[n2+j][n1+i]);
         level  = iabs(c_err) ;
 
         if (level  != 0)
@@ -2589,7 +2701,7 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
 
         //from now on decoder land
         ilev=c_err + isignab(level1,M1[n2+j][n1+i]);
-        curr_res[n2+j][n1+i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp;
+        mb_rres[n2+j][n1+i] = ilev * invlevelscale_sp[j][i] << qp_per_sp;
       }
       ACLevel[scan_pos] = 0;
     }
@@ -2597,22 +2709,22 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
   // * reset chroma coeffs
 
   if(cr_cbp_tmp==2)
-      cr_cbp=2;
+    cr_cbp=2;
   //     IDCT.
 
-      //     Horizontal.
+  //     Horizontal.
   for (n2=0; n2 <= BLOCK_SIZE; n2 += BLOCK_SIZE)
   {
     for (n1=0; n1 <= BLOCK_SIZE; n1 += BLOCK_SIZE)
     {
-      inverse4x4(curr_res, curr_res, n2, n1);
+      inverse4x4(mb_rres, mb_rres, n2, n1);
 
       //     Vertical.
       for (j=0; j < BLOCK_SIZE; j++)
       {
         for (i=0; i < BLOCK_SIZE; i++)
         {
-          enc_picture->imgUV[uv][img->pix_c_y+j+n2][img->pix_c_x+i +n1 ] = iClip3 (0, img->max_imgpel_value,rshift_rnd_sf(curr_res[n2+j][n1+i], DQ_BITS));
+          enc_picture->imgUV[uv][img->pix_c_y+j+n2][img->pix_c_x+i +n1 ] = iClip3 (0, img->max_imgpel_value,rshift_rnd_sf(mb_rres[n2+j][n1+i], DQ_BITS));
         }
       }
     }
@@ -2622,7 +2734,7 @@ int dct_chroma_sp2(Macroblock *currMB, int uv,int cr_cbp)
 }
 
 
-void select_dct(Macroblock *currMB)
+void select_dct(ImageParameters *img, Macroblock *currMB)
 {
   if (img->type!=SP_SLICE)
   {
@@ -2645,14 +2757,14 @@ void select_dct(Macroblock *currMB)
         dct_cr_4x4[0] = dct_chroma;
         dct_cr_4x4[1] = dct_chroma;
       }
-      
+
       if (currMB->qp_scaled[1] == 0)
       {
-         dct_cr_4x4[0] = dct_chroma_ls;
+        dct_cr_4x4[0] = dct_chroma_ls;
       }
       if (currMB->qp_scaled[2] == 0)
       {
-         dct_cr_4x4[1] = dct_chroma_ls;
+        dct_cr_4x4[1] = dct_chroma_ls;
       }
     }
     else
diff --git a/lencod/src/cabac.c b/lencod/src/cabac.c
index 8496df1..159773d 100644
--- a/lencod/src/cabac.c
+++ b/lencod/src/cabac.c
@@ -19,7 +19,7 @@
 #include "mb_access.h"
 
 #if TRACE
-#define CABAC_TRACE if (dp->bitstream->trace_enabled) trace2out_cabac (se)
+  #define CABAC_TRACE if (dp->bitstream->trace_enabled) trace2out_cabac (se)
 #else
   #define CABAC_TRACE
 #endif
@@ -106,9 +106,7 @@ MotionInfoContexts* create_contexts_MotionInfo(void)
  */
 TextureInfoContexts* create_contexts_TextureInfo(void)
 {
-  TextureInfoContexts*  enco_ctx;
-
-  enco_ctx = (TextureInfoContexts*) calloc(1, sizeof(TextureInfoContexts) );
+  TextureInfoContexts*  enco_ctx = (TextureInfoContexts*) calloc(1, sizeof(TextureInfoContexts) );
   if( enco_ctx == NULL )
     no_mem_exit("create_contexts_TextureInfo: enco_ctx");
 
@@ -131,8 +129,6 @@ void delete_contexts_MotionInfo(MotionInfoContexts *enco_ctx)
     return;
 
   free( enco_ctx );
-
-  return;
 }
 
 /*!
@@ -148,8 +144,6 @@ void delete_contexts_TextureInfo(TextureInfoContexts *enco_ctx)
     return;
 
   free( enco_ctx );
-
-  return;
 }
 
 
@@ -164,15 +158,14 @@ void writeFieldModeInfo_CABAC(SyntaxElement *se, DataPartition *dp)
 {
   EncodingEnvironmentPtr eep_dp = &(dp->ee_cabac);
   int curr_len = arienco_bits_written(eep_dp);
-  int a,b,act_ctx;
-  MotionInfoContexts *ctx         = (img->currentSlice)->mot_ctx;
-  Macroblock         *currMB      = &img->mb_data[img->current_mb_nr];
-  int                mb_field     = se->value1;
+  MotionInfoContexts *ctx     = (img->currentSlice)->mot_ctx;
+  Macroblock         *currMB  = &img->mb_data[img->current_mb_nr];
+  int                mb_field = se->value1;
 
-  a = currMB->mbAvailA ? img->mb_data[currMB->mbAddrA].mb_field : 0;
-  b = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
+  int a = currMB->mbAvailA ? img->mb_data[currMB->mbAddrA].mb_field : 0;
+  int b = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
 
-  act_ctx = a + b;
+  int act_ctx = a + b;
 
   biari_encode_symbol(eep_dp, (signed short) (mb_field != 0),&ctx->mb_aff_contexts[act_ctx]);
 
@@ -181,7 +174,6 @@ void writeFieldModeInfo_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -194,51 +186,31 @@ void writeMB_skip_flagInfo_CABAC(Macroblock *currMB, SyntaxElement *se, DataPart
 {
   EncodingEnvironmentPtr eep_dp = &(dp->ee_cabac);
   int curr_len = arienco_bits_written(eep_dp);
-  int a,b,act_ctx;
-  int bframe   = (img->type==B_SLICE);
-  MotionInfoContexts *ctx         = (img->currentSlice)->mot_ctx;
-  int                curr_mb_type = se->value1;
+  MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
+  int        curr_mb_type = se->value1;
+  int a = (currMB->mb_available_left != NULL && (currMB->mb_available_left->skip_flag == 0)) ? 1 : 0;
+  int b = (currMB->mb_available_up   != NULL && (currMB->mb_available_up  ->skip_flag == 0)) ? 1 : 0;
+  int act_ctx = a + b;
 
-  if (bframe)
+  if (img->type == B_SLICE)
   {
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
-      b = (currMB->mb_available_up->skip_flag==0 ? 1 : 0);
-
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
-      a = (currMB->mb_available_left->skip_flag==0 ? 1 : 0);
-
-    act_ctx = 7 + a + b;
+    act_ctx += 7;
 
     if (se->value1==0 && se->value2==0) // DIRECT mode, no coefficients
       biari_encode_symbol (eep_dp, 1, &ctx->mb_type_contexts[2][act_ctx]);
     else
       biari_encode_symbol (eep_dp, 0, &ctx->mb_type_contexts[2][act_ctx]);
 
-    currMB->skip_flag = (se->value1==0 && se->value2==0)?1:0;
+    currMB->skip_flag = (se->value1==0 && se->value2==0) ? 1 : 0;
   }
   else
   {
-    if (currMB->mb_available_up == NULL)
-      b = 0;
-    else
-      b = (( (currMB->mb_available_up)->skip_flag == 0) ? 1 : 0 );
-    if (currMB->mb_available_left == NULL)
-      a = 0;
-    else
-      a = (( (currMB->mb_available_left)->skip_flag == 0) ? 1 : 0 );
-
-    act_ctx = a + b;
-
     if (curr_mb_type==0) // SKIP
       biari_encode_symbol(eep_dp, 1,&ctx->mb_type_contexts[1][act_ctx]);
     else
       biari_encode_symbol(eep_dp, 0,&ctx->mb_type_contexts[1][act_ctx]);
 
-    currMB->skip_flag = (curr_mb_type==0)?1:0;
+    currMB->skip_flag = (curr_mb_type==0) ? 1 : 0;
   }
   se->context = act_ctx;
   se->value1  = 1 - currMB->skip_flag;
@@ -246,7 +218,6 @@ void writeMB_skip_flagInfo_CABAC(Macroblock *currMB, SyntaxElement *se, DataPart
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -260,27 +231,23 @@ void writeMB_skip_flagInfo_CABAC(Macroblock *currMB, SyntaxElement *se, DataPart
 void writeMB_transform_size_CABAC(SyntaxElement *se, DataPartition *dp)
 {
   EncodingEnvironmentPtr eep_dp = &(dp->ee_cabac);
-  int curr_len = arienco_bits_written(eep_dp);
-  int a, b;
-  int act_ctx = 0;
-  int act_sym;
-
   MotionInfoContexts *ctx         = (img->currentSlice)->mot_ctx;
   Macroblock         *currMB      = &img->mb_data[img->current_mb_nr];
 
+  int curr_len = arienco_bits_written(eep_dp);
+  int act_sym = currMB->luma_transform_size_8x8_flag;
+
 
-  b = (currMB->mb_available_up == NULL) ? 0 : currMB->mb_available_up->luma_transform_size_8x8_flag;
-  a = (currMB->mb_available_left == NULL) ? 0 :currMB->mb_available_left->luma_transform_size_8x8_flag;
+  int b = (currMB->mb_available_up == NULL) ? 0 : currMB->mb_available_up->luma_transform_size_8x8_flag;
+  int a = (currMB->mb_available_left == NULL) ? 0 :currMB->mb_available_left->luma_transform_size_8x8_flag;
+  int act_ctx     = a + b;
 
-  act_ctx     = a + b;
-  act_sym     = currMB->luma_transform_size_8x8_flag;
   se->context = act_ctx; // store context
   biari_encode_symbol(eep_dp, (signed short) (act_sym != 0), ctx->transform_size_contexts + act_ctx );
 
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -523,7 +490,6 @@ void writeMB_typeInfo_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 
@@ -586,37 +552,38 @@ void writeB8_typeInfo_CABAC(SyntaxElement *se, DataPartition *dp)
       biari_encode_symbol (eep_dp, 1, &b8_type_contexts[1][0]);
       act_sym--;
     }
-    if (act_sym<2)
+
+    if (act_sym < 2)
     {
       biari_encode_symbol (eep_dp, 0, &b8_type_contexts[1][1]);
       biari_encode_symbol (eep_dp, (signed short) (act_sym!=0), &b8_type_contexts[1][3]);
     }
-    else if (act_sym<6)
+    else if (act_sym < 6)
     {
       biari_encode_symbol (eep_dp, 1, &b8_type_contexts[1][1]);
       biari_encode_symbol (eep_dp, 0, &b8_type_contexts[1][2]);
-      csym=(((act_sym-2)>>1)&0x01) != 0;
+      csym=(((act_sym - 2) >> 1) & 0x01) != 0;
       biari_encode_symbol (eep_dp, csym, &b8_type_contexts[1][3]);
-      csym=((act_sym-2)&0x01) != 0;
+      csym=((act_sym - 2) & 0x01) != 0;
       biari_encode_symbol (eep_dp, csym, &b8_type_contexts[1][3]);
     }
     else
     {
       biari_encode_symbol (eep_dp, 1, &b8_type_contexts[1][1]);
       biari_encode_symbol (eep_dp, 1, &b8_type_contexts[1][2]);
-      csym=(((act_sym-6)>>2)&0x01);
+      csym=(((act_sym - 6)>> 2) & 0x01);
       if (csym)
       {
         biari_encode_symbol (eep_dp, 1, &b8_type_contexts[1][3]);
-        csym=((act_sym-6)&0x01) != 0;
+        csym=((act_sym - 6) & 0x01) != 0;
         biari_encode_symbol (eep_dp, csym, &b8_type_contexts[1][3]);
       }
       else
       {
         biari_encode_symbol (eep_dp, 0, &b8_type_contexts[1][3]);
-        csym=(((act_sym-6)>>1)&0x01) != 0;
+        csym=(((act_sym - 6) >> 1) & 0x01) != 0;
         biari_encode_symbol (eep_dp, csym, &b8_type_contexts[1][3]);
-        csym=((act_sym-6)&0x01) != 0;
+        csym=((act_sym - 6) & 0x01) != 0;
         biari_encode_symbol (eep_dp, csym, &b8_type_contexts[1][3]);
       }
     }
@@ -625,7 +592,6 @@ void writeB8_typeInfo_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -657,7 +623,6 @@ void writeIntraPredMode_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -679,7 +644,7 @@ void writeRefFrame_CABAC(SyntaxElement *se, DataPartition *dp)
   int   a, b;
   int   act_ctx;
   int   act_sym;
-  char** refframe_array = enc_picture->ref_idx[se->value2];
+  char** refframe_array = enc_picture->motion.ref_idx[se->value2];
 
   int bslice = (img->type==B_SLICE);
 
@@ -740,7 +705,6 @@ void writeRefFrame_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -778,7 +742,6 @@ void writeDquant_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 /*!
@@ -871,7 +834,6 @@ void writeMVD_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 
@@ -888,23 +850,15 @@ void writeCIPredMode_CABAC(SyntaxElement *se, DataPartition *dp)
   int curr_len = arienco_bits_written(eep_dp);
   TextureInfoContexts *ctx     = img->currentSlice->tex_ctx;
   Macroblock          *currMB  = &img->mb_data[img->current_mb_nr];
-  int                 act_ctx,a,b;
   int                 act_sym  = se->value1;
   
   Macroblock          *MbUp   = currMB->mb_available_up;
   Macroblock          *MbLeft = currMB->mb_available_left;
 
-  if (MbUp == NULL) 
-    b = 0;
-  else 
-    b = ((MbUp->c_ipred_mode != 0) && (MbUp->mb_type != IPCM)) ? 1 : 0;
+  int b = (MbUp   != NULL) ? (((MbUp->c_ipred_mode != 0) && (MbUp->mb_type != IPCM)) ? 1 : 0) : 0;
+  int a = (MbLeft != NULL) ? (((MbLeft->c_ipred_mode != 0) && (MbLeft->mb_type != IPCM)) ? 1 : 0) : 0;
 
-  if (MbLeft == NULL)
-    a = 0;
-  else
-    a =  ((MbLeft->c_ipred_mode != 0) && (MbLeft->mb_type != IPCM)) ? 1 : 0;
-
-  act_ctx = a+b;
+  int act_ctx = a + b;
 
   if (act_sym==0)
     biari_encode_symbol(eep_dp, 0, ctx->cipr_contexts + act_ctx );
@@ -917,7 +871,6 @@ void writeCIPredMode_CABAC(SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 
@@ -931,39 +884,30 @@ void writeCIPredMode_CABAC(SyntaxElement *se, DataPartition *dp)
 void writeCBP_BIT_CABAC (Macroblock* currMB, int b8, int bit, int cbp, int inter, EncodingEnvironmentPtr eep_dp, TextureInfoContexts *ctx)
 {
   PixelPos block_a;
-  int a, b;
+  int a = 0, b = 0;
 
   int mb_x=(b8 & 0x01)<<1;
   int mb_y=(b8 >> 1)<<1;
 
   if (mb_y == 0)
   {
-    if ((currMB->mb_available_up == NULL) || ((currMB->mb_available_up)->mb_type==IPCM))
-      b = 0;
-    else
+    if (!((currMB->mb_available_up == NULL) || ((currMB->mb_available_up)->mb_type==IPCM)))
     {
       b = (( ((currMB->mb_available_up)->cbp & (1<<(2+(mb_x>>1)))) == 0) ? 1 : 0);   //VG-ADD
     }
 
   }
   else
-    b = ( ((cbp & (1<<(mb_x/2))) == 0) ? 1: 0);
+    b = ( ((cbp & (1<<(mb_x >> 1))) == 0) ? 1: 0);
 
   if (mb_x == 0)
   {
     get4x4Neighbour(currMB, (mb_x << 2) - 1, (mb_y << 2), img->mb_size[IS_LUMA], &block_a);
-    if (block_a.available)
-    {
-      {
-        if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
-          a=0;
-        else
-          a = (( (img->mb_data[block_a.mb_addr].cbp & (1<<(2*(block_a.y>>1)+1))) == 0) ? 1 : 0); //VG-ADD
-      }
 
-    }
-    else
-      a=0;
+    if (block_a.available && (!(img->mb_data[block_a.mb_addr].mb_type==IPCM)))
+    {
+      a = (( (img->mb_data[block_a.mb_addr].cbp & (1<<(2*(block_a.y>>1)+1))) == 0) ? 1 : 0); //VG-ADD
+    }    
   }
   else
     a = ( ((cbp & (1<<mb_y)) == 0) ? 1: 0);
@@ -1041,22 +985,8 @@ void writeCBP_CABAC(Macroblock *currMB, SyntaxElement *se, DataPartition *dp)
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
-
-
-
-//static const int maxpos       [] = {15, 14, 63, 31, 31, 15,  3, 14,  7, 15, 15, 14, 63, 31, 31, 15, 15, 14, 63, 31, 31, 15};
-//static const int c1isdc       [] = { 1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1};
-//
-//static const int type2ctx_bcbp[] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5, 10, 11, 12, 13, 13, 14, 16, 17, 18, 19, 19, 20};
-//static const int type2ctx_map [] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; // 8
-//static const int type2ctx_last[] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; // 8
-//static const int type2ctx_one [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5, 10, 11, 12, 13, 13, 14, 16, 17, 18, 19, 19, 20}; // 7
-//static const int type2ctx_abs [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5, 10, 11, 12, 13, 13, 14, 16, 17, 18, 19, 19, 20}; // 7
-//static const int max_c2       [] = { 4,  4,  4,  4,  4,  4,  3,  4,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4}; // 9
-
 const int maxpos       [] = {15, 14, 63, 31, 31, 15,  3, 14,  7, 15, 15, 14, 63, 31, 31, 15, 15, 14, 63, 31, 31, 15};
 const int c1isdc       [] = { 1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1};
 
@@ -1077,7 +1007,6 @@ void write_and_store_CBP_block_bit (Macroblock* currMB, EncodingEnvironmentPtr e
 {
 #define BIT_SET(x,n)  ((int)(((x)&((int64)1<<(n)))>>(n)))
 
-
   int y_ac        = (type==LUMA_16AC || type==LUMA_8x8 || type==LUMA_8x4 || type==LUMA_4x8 || type==LUMA_4x4
                      || type==CB_16AC || type==CB_8x8 || type==CB_8x4 || type==CB_4x8 || type==CB_4x4
                      || type==CR_16AC || type==CR_8x8 || type==CR_8x4 || type==CR_4x8 || type==CR_4x4);
@@ -1119,9 +1048,9 @@ void write_and_store_CBP_block_bit (Macroblock* currMB, EncodingEnvironmentPtr e
     if (u_ac||v_ac)
     {
       if (block_a.available)
-        bit_pos_a = 4*block_a.y + block_a.x;
+        bit_pos_a = (block_a.y << 2) + block_a.x;
       if (block_b.available)
-        bit_pos_b = 4*block_b.y + block_b.x;
+        bit_pos_b = (block_b.y << 2) + block_b.x;
     }
   }
 
@@ -1268,21 +1197,21 @@ void write_and_store_CBP_block_bit (Macroblock* currMB, EncodingEnvironmentPtr e
     if (block_a.available)
     {
       if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
-        left_bit=1;
+        left_bit = 1;
       else
       {
         if(type==LUMA_8x8)
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[0],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[0],bit + bit_pos_a);
         else if (type==CB_8x8)
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[1],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[1],bit + bit_pos_a);
         else if (type==CR_8x8)
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[2],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[2],bit + bit_pos_a);
         else if ((type==CB_4x4)||(type==CB_4x8)||(type==CB_8x4)||(type==CB_16AC)||(type==CB_16DC))
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[1],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[1],bit + bit_pos_a);
         else if ((type==CR_4x4)||(type==CR_4x8)||(type==CR_8x4)||(type==CR_16AC)||(type==CR_16DC))
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[2],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[2],bit + bit_pos_a);
         else
-          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[0],bit+bit_pos_a);
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[0],bit + bit_pos_a);
       }
     }
 
@@ -1298,24 +1227,6 @@ void write_and_store_CBP_block_bit (Macroblock* currMB, EncodingEnvironmentPtr e
 
 //===== position -> ctx for MAP =====
 //--- zig-zag scan ----
-//static const int  pos2ctx_map8x8 [] = { 0,  1,  2,  3,  4,  5,  5,  4,  4,  3,  3,  4,  4,  4,  5,  5,
-//                                        4,  4,  4,  4,  3,  3,  6,  7,  7,  7,  8,  9, 10,  9,  8,  7,
-//                                        7,  6, 11, 12, 13, 11,  6,  7,  8,  9, 14, 10,  9,  8,  6, 11,
-//                                       12, 13, 11,  6,  9, 14, 10,  9, 11, 12, 13, 11 ,14, 10, 12, 14}; // 15 CTX
-//static const int  pos2ctx_map8x4 [] = { 0,  1,  2,  3,  4,  5,  7,  8,  9, 10, 11,  9,  8,  6,  7,  8,
-//                                        9, 10, 11,  9,  8,  6, 12,  8,  9, 10, 11,  9, 13, 13, 14, 14}; // 15 CTX
-//static const int  pos2ctx_map4x4 [] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 14}; // 15 CTX
-//static const int  pos2ctx_map2x4c[] = { 0,  0,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2}; // 15 CTX
-//static const int  pos2ctx_map4x4c[] = { 0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2}; // 15 CTX
-//static const int* pos2ctx_map    [] = {pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8, pos2ctx_map8x4,
-//                                       pos2ctx_map8x4, pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map4x4,
-//                                       pos2ctx_map2x4c, pos2ctx_map4x4c, 
-//
-//                                       pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8,pos2ctx_map8x4,
-//                                       pos2ctx_map8x4, pos2ctx_map4x4,  //Cb component
-//                                       pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8,pos2ctx_map8x4,
-//                                       pos2ctx_map8x4,pos2ctx_map4x4};  //Cr component
-
 const int  pos2ctx_map8x8 [] = { 0,  1,  2,  3,  4,  5,  5,  4,  4,  3,  3,  4,  4,  4,  5,  5,
                                         4,  4,  4,  4,  3,  3,  6,  7,  7,  7,  8,  9, 10,  9,  8,  7,
                                         7,  6, 11, 12, 13, 11,  6,  7,  8,  9, 14, 10,  9,  8,  6, 11,
@@ -1356,22 +1267,6 @@ static const int* pos2ctx_map_int[] = {pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_m
 
 
 //===== position -> ctx for LAST =====
-//static const int  pos2ctx_last8x8 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-//                                         2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-//                                         3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,
-//                                         5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8}; //  9 CTX
-//static const int  pos2ctx_last8x4 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,
-//                                         3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8}; //  9 CTX
-//static const int  pos2ctx_last4x4 [] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15}; // 15 CTX
-//static const int  pos2ctx_last2x4c[] = { 0,  0,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2}; // 15 CTX
-//static const int  pos2ctx_last4x4c[] = { 0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2}; // 15 CTX
-//static const int* pos2ctx_last    [] = {pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last8x8, pos2ctx_last8x4,
-//                                        pos2ctx_last8x4, pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last4x4,
-//                                        pos2ctx_last2x4c, pos2ctx_last4x4c,
-//                                        pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last8x8,pos2ctx_last8x4,
-//                                        pos2ctx_last8x4, pos2ctx_last4x4,  //Cb component
-//                                        pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last8x8,pos2ctx_last8x4,
-//                                        pos2ctx_last8x4, pos2ctx_last4x4}; //Cr component
 const int  pos2ctx_last8x8 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
                                          2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
                                          3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,
@@ -1430,7 +1325,8 @@ void write_significance_map (Macroblock* currMB, EncodingEnvironmentPtr eep_dp,
         last = (--coeff_ctr == 0);
 
         biari_encode_symbol(eep_dp, last, last_ctx + pos2ctx_last[type][k]);
-        if (last) return;
+        if (last) 
+          return;
       }
     }
     return;
@@ -1447,7 +1343,8 @@ void write_significance_map (Macroblock* currMB, EncodingEnvironmentPtr eep_dp,
         last = (--coeff_ctr == 0);
 
         biari_encode_symbol(eep_dp, last, last_ctx + pos2ctx_last[type][k]);
-        if (last) return;
+        if (last) 
+          return;
       }
     }
   }
@@ -1476,7 +1373,7 @@ void write_significant_coefficients (Macroblock* currMB, EncodingEnvironmentPtr
   {
     if (coeff[i]!=0)
     {
-      if (coeff[i]>0)
+      if (coeff[i] > 0)
       {
         absLevel =  coeff[i];  
         sign = 0;
@@ -1490,7 +1387,7 @@ void write_significant_coefficients (Macroblock* currMB, EncodingEnvironmentPtr
       greater_one = (absLevel > 1);
 
       //--- if coefficient is one ---
-      ctx = imin(c1,4);
+      ctx = imin(c1, 4);
       biari_encode_symbol (eep_dp, greater_one, one_contexts + ctx);
 
       if (greater_one)
@@ -1530,13 +1427,12 @@ void writeRunLevel_CABAC (Macroblock* currMB, SyntaxElement *se, DataPartition *
     pos += se->value2;
     coeff[pos++] = se->value1;
     coeff_ctr++;
-    //return;
   }
   else
   {
     TextureInfoContexts *tex_ctx = img->currentSlice->tex_ctx;
     //===== encode CBP-BIT =====
-    if (coeff_ctr>0)
+    if (coeff_ctr > 0)
     {
       write_and_store_CBP_block_bit  (currMB, eep_dp, se->context, 1, tex_ctx);
       //===== encode significance map =====
@@ -1555,7 +1451,6 @@ void writeRunLevel_CABAC (Macroblock* currMB, SyntaxElement *se, DataPartition *
   dp->bitstream->write_flag = 1;
   se->len = (arienco_bits_written(eep_dp) - curr_len);
   CABAC_TRACE;
-  return;
 }
 
 
@@ -1574,9 +1469,7 @@ void unary_bin_encode(EncodingEnvironmentPtr eep_dp,
                       BiContextTypePtr ctx,
                       int ctx_offset)
 {
-  unsigned int l;
-  BiContextTypePtr ictx;
-
+  
   if (symbol==0)
   {
     biari_encode_symbol(eep_dp, 0, ctx );
@@ -1585,13 +1478,11 @@ void unary_bin_encode(EncodingEnvironmentPtr eep_dp,
   else
   {
     biari_encode_symbol(eep_dp, 1, ctx );
-    l = symbol;
-    ictx = ctx+ctx_offset;
-    while ((--l)>0)
-      biari_encode_symbol(eep_dp, 1, ictx);
-    biari_encode_symbol(eep_dp, 0, ictx);
+    ctx += ctx_offset;
+    while ((--symbol) > 0)
+      biari_encode_symbol(eep_dp, 1, ctx);
+    biari_encode_symbol(eep_dp, 0, ctx);
   }
-  return;
 }
 
 /*!
@@ -1609,9 +1500,6 @@ void unary_bin_max_encode(EncodingEnvironmentPtr eep_dp,
                           int ctx_offset,
                           unsigned int max_symbol)
 {
-  unsigned int l;
-  BiContextTypePtr ictx;
-
   if (symbol==0)
   {
     biari_encode_symbol(eep_dp, 0, ctx );
@@ -1619,15 +1507,15 @@ void unary_bin_max_encode(EncodingEnvironmentPtr eep_dp,
   }
   else
   {
+    unsigned int l = symbol;
     biari_encode_symbol(eep_dp, 1, ctx );
-    l=symbol;
-    ictx=ctx+ctx_offset;
+    
+    ctx += ctx_offset;
     while ((--l)>0)
-      biari_encode_symbol(eep_dp, 1, ictx);
-    if (symbol<max_symbol)
-      biari_encode_symbol(eep_dp, 0, ictx);
+      biari_encode_symbol(eep_dp, 1, ctx);
+    if (symbol < max_symbol)
+      biari_encode_symbol(eep_dp, 0, ctx);
   }
-  return;
 }
 
 
@@ -1658,8 +1546,6 @@ void exp_golomb_encode_eq_prob( EncodingEnvironmentPtr eep_dp,
       break;
     }
   }
-
-  return;
 }
 
 /*!
@@ -1672,9 +1558,6 @@ void unary_exp_golomb_level_encode( EncodingEnvironmentPtr eep_dp,
                                     unsigned int symbol,
                                     BiContextTypePtr ctx)
 {
-  unsigned int l,k;
-  unsigned int exp_start = 13; // 15-2 : 0,1 level decision always sent
-
   if (symbol==0)
   {
     biari_encode_symbol(eep_dp, 0, ctx );
@@ -1682,17 +1565,18 @@ void unary_exp_golomb_level_encode( EncodingEnvironmentPtr eep_dp,
   }
   else
   {
+    unsigned int exp_start = 13; // 15-2 : 0,1 level decision always sent
+    unsigned int l=symbol;
+    unsigned int k = 1;
+
     biari_encode_symbol(eep_dp, 1, ctx );
-    l=symbol;
-    k=1;
     while (((--l)>0) && (++k <= exp_start))
       biari_encode_symbol(eep_dp, 1, ctx);
     if (symbol < exp_start) 
       biari_encode_symbol(eep_dp, 0, ctx);
     else 
-      exp_golomb_encode_eq_prob(eep_dp,symbol-exp_start,0);
+      exp_golomb_encode_eq_prob(eep_dp,symbol - exp_start, 0);
   }
-  return;
 }
 
 
@@ -1707,36 +1591,31 @@ void unary_exp_golomb_mv_encode(EncodingEnvironmentPtr eep_dp,
                                 unsigned int symbol,
                                 BiContextTypePtr ctx,
                                 unsigned int max_bin)
-{
-  unsigned int l,k;
-  unsigned int bin=1;
-  BiContextTypePtr ictx=ctx;
-  unsigned int exp_start = 8; // 9-1 : 0 mvd decision always sent
-
+{  
   if (symbol==0)
   {
-    biari_encode_symbol(eep_dp, 0, ictx );
+    biari_encode_symbol(eep_dp, 0, ctx );
     return;
   }
   else
   {
-    biari_encode_symbol(eep_dp, 1, ictx );
-    l=symbol;
-    k=1;
-    ictx++;
+    unsigned int bin=1;
+    unsigned int exp_start = 8; // 9-1 : 0 mvd decision always sent
+    unsigned int l = symbol, k = 1;
+    biari_encode_symbol(eep_dp, 1, ctx++ );
+    
     while (((--l)>0) && (++k <= exp_start))
     {
-      biari_encode_symbol(eep_dp, 1, ictx  );
-      if ((++bin)==2) 
-        ictx++;
-      if (bin==max_bin) 
-        ictx++;
+      biari_encode_symbol(eep_dp, 1, ctx  );
+      if ((++bin) == 2) 
+        ctx++;
+      if (bin == max_bin) 
+        ctx++;
     }
     if (symbol < exp_start) 
-      biari_encode_symbol(eep_dp, 0, ictx);
+      biari_encode_symbol(eep_dp, 0, ctx);
     else 
-      exp_golomb_encode_eq_prob(eep_dp,symbol-exp_start,3);
+      exp_golomb_encode_eq_prob(eep_dp, symbol - exp_start, 3);
   }
-  return;
 }
 
diff --git a/lencod/src/cconv_yuv2rgb.c b/lencod/src/cconv_yuv2rgb.c
new file mode 100644
index 0000000..975a375
--- /dev/null
+++ b/lencod/src/cconv_yuv2rgb.c
@@ -0,0 +1,122 @@
+
+/*!
+ *************************************************************************************
+ * \file img_distortion.c
+ *
+ * \brief
+ *    YUV to RGB color conversion
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *************************************************************************************
+ */
+#include "contributors.h"
+#include "global.h"
+#include "img_distortion.h"
+
+#define YUV2RGB_YOFFSET
+
+//YUV to RGB conversion
+#ifdef YUV2RGB_YOFFSET
+#define OFFSET_Y 16
+static const float K0 = 1.164f;
+static const float K1 = 1.596f;
+static const float K2 = 0.391f;
+static const float K3 = 0.813f;
+static const float K4 = 2.018f;
+static int offset_y, offset_cr;
+#else
+static const float K0 = 1.000f;
+static const float K1 = 1.402f;
+static const float K2 = 0.34414f;
+static const float K3 = 0.71414f;
+static const float K4 = 1.772f;
+#endif
+static int wk0, wk1, wk2, wk3, wk4;
+
+ImageStructure imgRGB_src, imgRGB_ref;
+
+void init_YUVtoRGB(void)
+{ 
+  float conv_scale = (float) (65536.0f);
+
+  wk0 = float2int(  conv_scale * K0);
+  wk1 = float2int(  conv_scale * K1);
+  wk2 = float2int( -conv_scale * K2);
+  wk3 = float2int( -conv_scale * K3);
+  wk4 = float2int(  conv_scale * K4);
+
+#ifdef YUV2RGB_YOFFSET
+  offset_y = OFFSET_Y << (params->output.bit_depth[0] - 8);
+  offset_cr = 1 << (params->output.bit_depth[0] - 1);
+#endif
+}
+
+/*! 
+*************************************************************************************
+* \brief
+*    YUV to RGB conversion
+*    ITU 601 with and without offset consideration
+*    Upsampling by repetition of chroma samples in case of 4:2:0 and 4:2:2
+*    Method not support for 4:0:0 content
+*************************************************************************************
+*/
+void YUVtoRGB(ImageStructure *YUV, ImageStructure *RGB)
+{
+  static int i, j, j_cr, i_cr;
+  static int sy, su, sv;
+  static int wbuv, wguv, wruv;
+  static imgpel *Y, *U, *V, *R, *G, *B;
+  FrameFormat format = YUV->format;
+  int width = format.width;
+  int height = format.height;
+  int max_value = format.max_value[0];
+
+  // Color conversion
+  for (j = 0; j < height; j++)
+  {
+    j_cr = j >> shift_cr_y;
+    Y = YUV->data[0][j];
+    U = YUV->data[1][j_cr];
+    V = YUV->data[2][j_cr];
+    R = RGB->data[0][j];
+    G = RGB->data[1][j];
+    B = RGB->data[2][j];
+
+    for (i = 0; i < width; i++)
+    {
+      i_cr = i >> shift_cr_x;
+
+      su = U[i_cr] - offset_cr;
+      sv = V[i_cr] - offset_cr;
+
+      wruv = wk1 * sv;
+      wguv = wk2 * su + wk3 * sv;
+      wbuv = wk4 * su;
+
+#ifdef YUV2RGB_YOFFSET // Y offset value of 16 is considered
+      sy = wk0 * (Y[i] - offset_y);
+#else
+      sy = wk0 * Y[i];
+#endif
+
+      R[i] = iClip1( max_value, rshift_rnd(sy + wruv, 16));
+      G[i] = iClip1( max_value, rshift_rnd(sy + wguv, 16));
+      B[i] = iClip1( max_value, rshift_rnd(sy + wbuv, 16));
+    }
+  }
+  // Setting RGB FrameFormat
+  RGB->format = format;  // copy format information from YUV to RGB
+  RGB->format.yuv_format = 3;
+  RGB->format.rgb_format = 1;
+  RGB->format.height_cr = format.height;
+  RGB->format.width_cr = format.width;
+  for (i = 1; i < 3; i++)
+  {
+    RGB->format.size_cmp[i] = format.size_cmp[0];
+    RGB->format.bit_depth[i] = format.bit_depth[0];
+    RGB->format.max_value[i] = max_value;
+    RGB->format.max_value_sq[i] = format.max_value_sq[0];
+  }
+}
diff --git a/lencod/src/configfile.c b/lencod/src/configfile.c
index 38fbdb0..0d82084 100644
--- a/lencod/src/configfile.c
+++ b/lencod/src/configfile.c
@@ -149,6 +149,23 @@ static void getNumberOfFrames (void)
   params->no_frames = (int) (((fsize - params->infile_header)/ isize) - params->start_frame - 1) / (1 + params->jumpd) + 1;
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Updates images max values
+ *
+ ************************************************************************
+ */
+static void updateMaxValue(FrameFormat *format)
+{
+  format->max_value[0] = (1 << format->bit_depth[0]) - 1;
+  format->max_value_sq[0] = format->max_value[0] * format->max_value[0];
+  format->max_value[1] = (1 << format->bit_depth[1]) - 1;
+  format->max_value_sq[1] = format->max_value[1] * format->max_value[1];
+  format->max_value[2] = (1 << format->bit_depth[2]) - 1;
+  format->max_value_sq[2] = format->max_value[2] * format->max_value[2];
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -159,6 +176,9 @@ static void getNumberOfFrames (void)
 static void updateOutFormat(InputParameters *params)
 {
 
+  params->output.yuv_format = params->yuv_format;
+  params->source.yuv_format = params->yuv_format;
+
   if (params->src_resize == 0)
   {
     params->output.width = params->source.width;
@@ -167,8 +187,8 @@ static void updateOutFormat(InputParameters *params)
 
   if (params->yuv_format == YUV400) // reset bitdepth of chroma for 400 content
   {
-    params->source.bit_depth[1] = 0;
-    params->output.bit_depth[1] = 0;
+    params->source.bit_depth[1] = 8;
+    params->output.bit_depth[1] = 8;
     params->source.width_cr  = 0;
     params->source.height_cr = 0;
     params->output.width_cr  = 0;
@@ -177,22 +197,28 @@ static void updateOutFormat(InputParameters *params)
   else
   {
     params->source.width_cr  = (params->source.width  * mb_width_cr [params->yuv_format]) >> 4;
-    params->source.height_cr = (params->source.height * mb_width_cr [params->yuv_format]) >> 4;    
+    params->source.height_cr = (params->source.height * mb_height_cr[params->yuv_format]) >> 4;
     params->output.width_cr  = (params->output.width  * mb_width_cr [params->yuv_format]) >> 4;
     params->output.height_cr = (params->output.height * mb_height_cr[params->yuv_format]) >> 4;
   }
 
   // source size
-  params->source.size_cmp[0] = params->source.width * params->source.height;
+  params->source.size_cmp[0] = params->source.width    * params->source.height;
   params->source.size_cmp[1] = params->source.width_cr * params->source.height_cr;
   params->source.size_cmp[2] = params->source.size_cmp[1];
-  params->source.size = params->source.size_cmp[0] + params->source.size_cmp[1] + params->source.size_cmp[2];
+  params->source.size        = params->source.size_cmp[0] + params->source.size_cmp[1] + params->source.size_cmp[2];
+  params->source.mb_width    = params->source.width  / MB_BLOCK_SIZE;
+  params->source.mb_height   = params->source.height / MB_BLOCK_SIZE;
+
 
   // output size (excluding padding)
   params->output.size_cmp[0] = params->output.width * params->source.height;
   params->output.size_cmp[1] = params->output.width_cr * params->source.height_cr;
   params->output.size_cmp[2] = params->output.size_cmp[1];
-  params->source.size = params->output.size_cmp[0] + params->output.size_cmp[1] + params->output.size_cmp[2];
+  params->output.size        = params->output.size_cmp[0] + params->output.size_cmp[1] + params->output.size_cmp[2];
+  params->output.mb_width    = params->output.width  / MB_BLOCK_SIZE;
+  params->output.mb_height   = params->output.height / MB_BLOCK_SIZE;
+
 
   // both chroma components have the same bitdepth
   params->source.bit_depth[2] = params->source.bit_depth[1];
@@ -205,6 +231,9 @@ static void updateOutFormat(InputParameters *params)
     params->output.bit_depth[1] = params->source.bit_depth[1];
     params->output.bit_depth[2] = params->source.bit_depth[2];
   }
+  
+  updateMaxValue(&params->source);
+  updateMaxValue(&params->output);
 }
 
 
@@ -367,7 +396,7 @@ char *GetConfigFileContent (char *Filename)
   }
 
   FileSize = ftell (f);
-  if (FileSize < 0 || FileSize > 60000)
+  if (FileSize < 0 || FileSize > 100000)
   {
     snprintf (errortext, ET_SIZE, "Unreasonable Filesize %ld reported by ftell for configuration file %s.", FileSize, Filename);
     return NULL;
@@ -1064,45 +1093,51 @@ static void PatchInp (void)
     read_slice_group_info();
   }
 
-  if (params->ReferenceReorder && (params->PicInterlace || params->MbInterlace))
+  if (params->WPMCPrecision && (params->RDPictureDecision != 1 || params->GenerateMultiplePPS != 1) )
   {
-    snprintf(errortext, ET_SIZE, "ReferenceReorder Not supported with Interlace encoding methods\n");
+    snprintf(errortext, ET_SIZE, "WPMCPrecision requires both RDPictureDecision=1 and GenerateMultiplePPS=1.\n");
     error (errortext, 400);
   }
-
-  if (params->PocMemoryManagement && (params->PicInterlace || params->MbInterlace))
+  if (params->WPMCPrecision && params->WPMCPrecFullRef && params->num_ref_frames < 16 )
   {
-    snprintf(errortext, ET_SIZE, "PocMemoryManagement not supported with Interlace encoding methods\n");
+    params->num_ref_frames++;
+    if ( params->P_List0_refs )
+      params->P_List0_refs++;
+    else
+      params->P_List0_refs = params->num_ref_frames;
+    if ( params->B_List0_refs )
+      params->B_List0_refs++;
+    else
+      params->B_List0_refs = params->num_ref_frames;
+    if ( params->B_List1_refs )
+      params->B_List1_refs++;
+    else
+      params->B_List1_refs = params->num_ref_frames;
+  }
+  else if ( params->WPMCPrecision && params->WPMCPrecFullRef )
+  {
+    snprintf(errortext, ET_SIZE, "WPMCPrecFullRef requires NumberReferenceFrames < 16.\n");
     error (errortext, 400);
   }
 
-  // frame/field consistency check
-  if (params->PicInterlace != FRAME_CODING && params->PicInterlace != ADAPTIVE_CODING && params->PicInterlace != FIELD_CODING)
+  if (params->ReferenceReorder && params->MbInterlace )
   {
-    snprintf (errortext, ET_SIZE, "Unsupported PicInterlace=%d, use frame based coding=0 or field based coding=1 or adaptive=2",params->PicInterlace);
+    snprintf(errortext, ET_SIZE, "ReferenceReorder not supported with MBAFF\n");
     error (errortext, 400);
   }
 
-  // frame/field consistency check
-  if (params->MbInterlace != FRAME_CODING && params->MbInterlace != ADAPTIVE_CODING && params->MbInterlace != FIELD_CODING && params->MbInterlace != FRAME_MB_PAIR_CODING)
+  if (params->PocMemoryManagement && params->MbInterlace )
   {
-    snprintf (errortext, ET_SIZE, "Unsupported MbInterlace=%d, use frame based coding=0 or field based coding=1 or adaptive=2 or frame MB pair only=3",params->MbInterlace);
+    snprintf(errortext, ET_SIZE, "PocMemoryManagement not supported with MBAFF\n");
     error (errortext, 400);
   }
 
-
   if ((!params->rdopt)&&(params->MbInterlace))
   {
     snprintf(errortext, ET_SIZE, "MB AFF is not compatible with non-rd-optimized coding.");
     error (errortext, 500);
   }
 
-  /*if (params->rdopt>2)
-  {
-    snprintf(errortext, ET_SIZE, "RDOptimization=3 mode has been deactivated do to diverging of real and simulated decoders.");
-    error (errortext, 500);
-  }*/
-
   // check RDoptimization mode and profile. FMD does not support Frex Profiles.
   if (params->rdopt==2 && ( params->ProfileIDC>=FREXT_HP || params->ProfileIDC==FREXT_CAVLC444 ))
   {
@@ -1167,35 +1202,35 @@ static void PatchInp (void)
   // Rate control
   if(params->RCEnable)
   {
+    if (params->basicunit == 0)
+      params->basicunit = (params->output.height + img->auto_crop_bottom)*(params->output.width + img->auto_crop_right)/256;
+
     if ( ((params->output.height + img->auto_crop_bottom)*(params->output.width + img->auto_crop_right)/256) % params->basicunit != 0)
     {
       snprintf(errortext, ET_SIZE, "Frame size in macroblocks must be a multiple of BasicUnit.");
       error (errortext, 500);
     }
-    // input basicunit represents the number of BUs in a frame
-    // internal basicunit is the number of MBs in a BU
-    params->basicunit = ((params->output.height + img->auto_crop_bottom)*(params->output.width + img->auto_crop_right)/256) / params->basicunit;
 
-    if ( params->RCEnable && params->RCUpdateMode == RC_MODE_1 && 
+    if ( params->RCUpdateMode == RC_MODE_1 && 
       !( (params->intra_period == 1 || params->idr_period == 1 || params->BRefPictures == 2 ) && !params->successive_Bframe ) )
     {
       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 only for all intra or all B-slice coding.");
       error (errortext, 500);
     }
 
-    if ( params->RCEnable && params->BRefPictures == 2 && params->intra_period == 0 && params->RCUpdateMode != RC_MODE_1 )
+    if ( params->BRefPictures == 2 && params->intra_period == 0 && params->RCUpdateMode != RC_MODE_1 )
     {
       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 for all B-slice coding.");
       error (errortext, 500);
     }
 
-    if ( params->RCEnable && params->HierarchicalCoding && params->RCUpdateMode != RC_MODE_2 && params->RCUpdateMode != RC_MODE_3 )
+    if ( params->HierarchicalCoding && params->RCUpdateMode != RC_MODE_2 && params->RCUpdateMode != RC_MODE_3 )
     {
       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 2 or 3 for hierarchical B-picture coding.");
       error (errortext, 500);
     }
 
-    if ( params->RCEnable && (params->RCUpdateMode != RC_MODE_1) && (params->intra_period == 1) )
+    if ( (params->RCUpdateMode != RC_MODE_1) && (params->intra_period == 1) )
     {
       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 for all intra coding.");
       error (errortext, 500);
@@ -1278,24 +1313,18 @@ static void PatchInp (void)
     params->ChromaMEEnable = 0;
   }
 
-  if ( (0 == params->ChromaMCBuffer) && (( params->yuv_format ==  YUV444) && (!params->separate_colour_plane_flag)) )
+  if ( (params->ChromaMCBuffer == 0) && (( params->yuv_format ==  YUV444) && (!params->separate_colour_plane_flag)) )
   {
     fprintf(stderr, "Warning: Enabling ChromaMCBuffer for YUV444 combined color coding.\n");
     params->ChromaMCBuffer = 1;
   }
 
-  if (params->EnableOpenGOP && params->PicInterlace)
-  {
-    snprintf(errortext, ET_SIZE, "Open GOP currently not supported for Field coded pictures.");
-    error (errortext, 500);
-  }
 
   if (params->EnableOpenGOP)
     params->ReferenceReorder = 1;
 
-
   if (params->SearchMode != EPZS)
-      params->EPZSSubPelGrid = 0;
+    params->EPZSSubPelGrid = 0;
 
   params->EPZSGrid = params->EPZSSubPelGrid << 1;
 
@@ -1362,6 +1391,9 @@ static void PatchInp (void)
     {
       printf("RDO Quantization currently not supported with MBAFF. Option disabled.\n");
       params->UseRDOQuant = 0;
+      params->RDOQ_QP_Num = 1;
+      params->RDOQ_CP_MV = 0;
+      params->RDOQ_CP_Mode = 0;
     }
     else
     {
diff --git a/lencod/src/conformance.c b/lencod/src/conformance.c
index 7d81624..dffbb6d 100644
--- a/lencod/src/conformance.c
+++ b/lencod/src/conformance.c
@@ -199,11 +199,6 @@ void ProfileCheck(void)
       snprintf(errortext, ET_SIZE, "CABAC is not allowed in Extended profile (ProfileIDC = 88).");
       error (errortext, 500);
     }
-    if ((params->PicInterlace) ||(params->MbInterlace))
-    {
-      snprintf(errortext, ET_SIZE, "Interlace tools are not allowed in Extended profile (ProfileIDC = 88).");
-      error (errortext, 500);
-    }
   }
 
   //FRExt
diff --git a/lencod/src/context_ini.c b/lencod/src/context_ini.c
index 96a7348..a7ed4cc 100644
--- a/lencod/src/context_ini.c
+++ b/lencod/src/context_ini.c
@@ -239,7 +239,7 @@ double XRate (BiContextTypePtr ctx, const int* model)
 {
   int     ctx_state, mod_state;
   double  weight, xr = 0.0;
-  int     qp = imax(0,img->qp);
+  int     qp = imax(0, img->qp);
 
   weight    = dmin (1.0, (double)ctx->count/(double)RELIABLE_COUNT);
 
diff --git a/lencod/src/decoder.c b/lencod/src/decoder.c
deleted file mode 100644
index e0f68ed..0000000
--- a/lencod/src/decoder.c
+++ /dev/null
@@ -1,669 +0,0 @@
-
-/*!
- *************************************************************************************
- * \file decoder.c
- *
- * \brief
- *    Contains functions that implement the "decoders in the encoder" concept for the
- *    rate-distortion optimization with losses.
- * \date
- *    October 22nd, 2001
- *
- * \author
- *    Main contributors (see contributors.h for copyright, address and
- *    affiliation details)
- *    - Dimitrios Kontopodis                    <dkonto@eikon.tum.de>
- *************************************************************************************
- */
-
-#include "global.h"
-#include "refbuf.h"
-#include "image.h"
-
-static void Get_Reference_Block(imgpel **imY, int block_y, int block_x, int mvhor, int mvver, imgpel **out);
-static byte Get_Reference_Pixel(imgpel **imY, int y, int x);
-static void DecOneForthPix(imgpel **dY, imgpel ***dref);
-static void Build_Status_Map(byte **s_map);
-static void Error_Concealment(imgpel **inY, byte **s_map, imgpel ***refY);
-static void Conceal_Error(imgpel **inY, int mb_y, int mb_x, imgpel ***refY, byte **s_map);
-/*!
- *************************************************************************************
- * \brief
- *    decodes one 8x8 partition
- *
- * \note
- *    Gives the expected value in the decoder of one 8x8 block. This is done based on the
- *    stored reconstructed residue decs->resY[][], the reconstructed values imgY[][]
- *    and the motion vectors. The decoded 8x8 block is moved to decs->decY[][].
- *************************************************************************************
- */
-void decode_one_b8block (int decoder, int mbmode, int b8block, short b8mode, short b8ref)
-{
-  int i,j,block_y,block_x,bx,by;
-  int ref_inx = (IMG_NUMBER-1)%img->num_ref_frames;
-
-  int mv[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE];
-  int resY_tmp[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
-
-  int i0 = (b8block%2)<<3,   i1 = i0+8,   bx0 = i0>>2,   bx1 = bx0+2;
-  int j0 = (b8block/2)<<3,   j1 = j0+8,   by0 = j0>>2,   by1 = by0+2;
-
-  if (img->type==I_SLICE)
-  {
-    for(i=i0;i<i1;i++)
-    for(j=j0;j<j1;j++)
-    {
-      decs->decY[decoder][img->pix_y+j][img->pix_x+i]=enc_picture->imgY[img->pix_y+j][img->pix_x+i];
-    }
-  }
-  else
-  {
-    if (mbmode==0 && (img->type==P_SLICE || (img->type==B_SLICE && img->nal_reference_idc>0)))
-    {
-      for(i=i0;i<i1;i++)
-      for(j=j0;j<j1;j++)
-      {
-        resY_tmp[j][i]=0;
-      }
-      for (by=by0; by<by1; by++)
-      for (bx=bx0; bx<bx1; bx++)
-      {
-        mv[0][by][bx] = mv[1][by][bx] = 0;
-      }
-    }
-    else
-    {
-      if (b8mode>=1 && b8mode<=7)
-      {
-        for (by=by0; by<by1; by++)
-        for (bx=bx0; bx<bx1; bx++)
-        {
-          mv[0][by][bx] = img->all_mv[LIST_0][b8ref][b8mode][by][bx][0];
-          mv[1][by][bx] = img->all_mv[LIST_0][b8ref][b8mode][by][bx][1];
-        }
-      }
-      else
-      {
-        for (by=by0; by<by1; by++)
-        for (bx=bx0; bx<bx1; bx++)
-        {
-          mv[0][by][bx] = mv[1][by][bx] = 0;
-        }
-      }
-
-      for(i=i0;i<i1;i++)
-      for(j=j0;j<j1;j++)
-      {
-        resY_tmp[j][i]=decs->resY[j][i];
-      }
-    }
-
-    // Decode Luminance
-    if ((b8mode>=1 && b8mode<=7) || (mbmode==0 && (img->type==P_SLICE || (img->type==B_SLICE && img->nal_reference_idc>0))))
-    {
-      for (by=by0; by<by1; by++)
-      for (bx=bx0; bx<bx1; bx++)
-      {
-        block_x = img->block_x+bx;
-        block_y = img->block_y+by;
-        if (img->type == B_SLICE && enc_picture != enc_frame_picture[0])
-          ref_inx = (IMG_NUMBER - b8ref - 2)%img->num_ref_frames;
-
-        Get_Reference_Block (decs->decref[decoder][ref_inx], block_y, block_x, mv[0][by][bx], mv[1][by][bx], decs->RefBlock);
-
-        for (j=0; j<4; j++)
-        for (i=0; i<4; i++)
-        {
-          decs->decY[decoder][block_y*4+j][block_x*4+i] = iClip3 (0, img->max_imgpel_value, resY_tmp[by*4+j][bx*4+i] + decs->RefBlock[j][i]);
-        }
-      }
-    }
-    else
-    {
-      // Intra Refresh - Assume no spatial prediction
-      for(i=i0;i<i1;i++)
-      for(j=j0;j<j1;j++)
-      {
-        decs->decY[decoder][img->pix_y+j][img->pix_x+i] = enc_picture->imgY[img->pix_y+j][img->pix_x+i];
-      }
-    }
-  }
-}
-
-
-/*!
- *************************************************************************************
- * \brief
- *    decodes one macroblock
- *************************************************************************************
- */
-void decode_one_mb (int decoder, Macroblock* currMB)
-{
-  decode_one_b8block (decoder, currMB->mb_type, 0, currMB->b8mode[0], enc_picture->ref_idx[LIST_0][img->block_y+0][img->block_x+0]);//refFrArr[img->block_y+0][img->block_x+0]);
-  decode_one_b8block (decoder, currMB->mb_type, 1, currMB->b8mode[1], enc_picture->ref_idx[LIST_0][img->block_y+0][img->block_x+2]);//refFrArr[img->block_y+0][img->block_x+2]);
-  decode_one_b8block (decoder, currMB->mb_type, 2, currMB->b8mode[2], enc_picture->ref_idx[LIST_0][img->block_y+2][img->block_x+0]);//refFrArr[img->block_y+2][img->block_x+0]);
-  decode_one_b8block (decoder, currMB->mb_type, 3, currMB->b8mode[3], enc_picture->ref_idx[LIST_0][img->block_y+2][img->block_x+2]);//refFrArr[img->block_y+2][img->block_x+2]);
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Finds the reference MB given the decoded reference frame
- * \note
- *    This is based on the function UnifiedOneForthPix, only it is modified to
- *    be used at the "many decoders in the encoder" RD optimization. In this case
- *    we dont want to keep full upsampled reference frames for all decoders, so
- *    we just upsample when it is necessary.
- * \param imY
- *    The frame to be upsampled
- * \param block_y
- *    The row of the block, whose prediction we want to find
- * \param block_x
- *    The column of the block, whose prediction we want to track
- * \param mvhor
- *    Motion vector, horizontal part
- * \param mvver
- *    Motion vector, vertical part
- * \param out
- *    Output: The prediction for the block (block_y, block_x)
- *************************************************************************************
- */
-static void Get_Reference_Block(imgpel **imY,
-                         int block_y,
-                         int block_x,
-                         int mvhor,
-                         int mvver,
-                         imgpel **out)
-{
-  int i,j,y,x;
-
-  y = block_y * BLOCK_SIZE * 4 + mvver;
-  x = block_x * BLOCK_SIZE * 4 + mvhor;
-
-  for (j=0; j<BLOCK_SIZE; j++)
-    for (i=0; i<BLOCK_SIZE; i++)
-      out[j][i] = Get_Reference_Pixel(imY, y+j*4, x+i*4);
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Finds a pixel (y,x) of the upsampled reference frame
- * \note
- *    This is based on the function UnifiedOneForthPix, only it is modified to
- *    be used at the "many decoders in the encoder" RD optimization. In this case
- *    we dont want to keep full upsampled reference frames for all decoders, so
- *    we just upsample when it is necessary.
- *************************************************************************************
- */
-static byte Get_Reference_Pixel(imgpel **imY, int y_pos, int x_pos)
-{
-
-  int dx, x;
-  int dy, y;
-  int maxold_x,maxold_y;
-
-  int result = 0, result1, result2;
-  int pres_x;
-  int pres_y;
-
-  int tmp_res[6];
-
-  static const int COEF[6] = {  1, -5, 20, 20, -5, 1 };
-
-
-  dx = x_pos&3;
-  dy = y_pos&3;
-  x_pos = (x_pos-dx)/4;
-  y_pos = (y_pos-dy)/4;
-  maxold_x = img->width-1;
-  maxold_y = img->height-1;
-
-  if (dx == 0 && dy == 0) 
-  { /* fullpel position */
-    result = imY[iClip3(0,maxold_y,y_pos)][iClip3(0,maxold_x,x_pos)];
-  }
-  else { /* other positions */
-
-    if (dy == 0) 
-    {
-      pres_y = iClip3(0,maxold_y,y_pos);
-      for(x=-2;x<4;x++) 
-      {
-        pres_x = iClip3(0,maxold_x,x_pos+x);
-        result += imY[pres_y][pres_x]*COEF[x+2];
-      }
-
-      result = iClip1( img->max_imgpel_value, (result+16)/32);
-
-      if (dx == 1) 
-      {
-        result = (result + imY[pres_y][iClip3(0,maxold_x,x_pos)])/2;
-      }
-      else if (dx == 3) 
-      {
-        result = (result + imY[pres_y][iClip3(0,maxold_x,x_pos+1)])/2;
-      }
-    }
-    else if (dx == 0) 
-    {
-      pres_x = iClip3(0,maxold_x,x_pos);
-      for(y=-2;y<4;y++) 
-      {
-        pres_y = iClip3(0,maxold_y,y_pos+y);
-        result += imY[pres_y][pres_x]*COEF[y+2];
-      }
-
-      result = iClip1( img->max_imgpel_value, (result+16)/32);
-
-      if (dy == 1) 
-      {
-        result = (result + imY[iClip3(0,maxold_y,y_pos)][pres_x])/2;
-      }
-      else if (dy == 3) 
-      {
-        result = (result + imY[iClip3(0,maxold_y,y_pos+1)][pres_x])/2;
-      }
-    }
-    else if (dx == 2) 
-    {
-
-      for(y=-2;y<4;y++) 
-      {
-        result = 0;
-        pres_y = iClip3(0,maxold_y,y_pos+y);
-        for(x=-2;x<4;x++) 
-        {
-          pres_x = iClip3(0,maxold_x,x_pos+x);
-          result += imY[pres_y][pres_x]*COEF[x+2];
-        }
-        tmp_res[y+2] = result;
-      }
-
-      result = 0;
-      for(y=-2;y<4;y++) 
-      {
-        result += tmp_res[y+2]*COEF[y+2];
-      }
-
-      result = iClip1(img->max_imgpel_value, (result+512)/1024);
-
-      if (dy == 1) 
-      {
-        result = (result + iClip1(img->max_imgpel_value, (tmp_res[2]+16)/32))/2;
-      }
-      else if (dy == 3) 
-      {
-        result = (result + iClip1(img->max_imgpel_value, (tmp_res[3]+16)/32))/2;
-      }
-    }
-    else if (dy == 2) 
-    {
-
-      for(x=-2;x<4;x++) 
-      {
-        result = 0;
-        pres_x = iClip3(0,maxold_x,x_pos+x);
-        for(y=-2;y<4;y++) 
-        {
-          pres_y = iClip3(0,maxold_y,y_pos+y);
-          result += imY[pres_y][pres_x]*COEF[y+2];
-        }
-        tmp_res[x+2] = result;
-      }
-
-      result = 0;
-      for(x=-2;x<4;x++) 
-      {
-        result += tmp_res[x+2]*COEF[x+2];
-      }
-
-      result = iClip1(img->max_imgpel_value, (result+512)/1024);
-
-      if (dx == 1) 
-      {
-        result = (result + iClip1( img->max_imgpel_value, (tmp_res[2]+16)/32))/2;
-      }
-      else {
-        result = (result + iClip1( img->max_imgpel_value, (tmp_res[3]+16)/32))/2;
-      }
-    }
-    else {
-
-      result = 0;
-      pres_y = dy == 1 ? y_pos : y_pos+1;
-      pres_y = iClip3(0,maxold_y,pres_y);
-
-      for(x=-2;x<4;x++) 
-      {
-        pres_x = iClip3(0,maxold_x,x_pos+x);
-        result += imY[pres_y][pres_x]*COEF[x+2];
-      }
-
-      result1 = iClip1( img->max_imgpel_value, (result+16)/32);
-
-      result = 0;
-      pres_x = dx == 1 ? x_pos : x_pos+1;
-      pres_x = iClip3(0,maxold_x,pres_x);
-
-      for(y=-2;y<4;y++) 
-      {
-        pres_y = iClip3(0,maxold_y,y_pos+y);
-        result += imY[pres_y][pres_x]*COEF[y+2];
-      }
-
-      result2 = iClip1( img->max_imgpel_value, (result+16)/32);
-      result = (result1+result2)/2;
-    }
-  }
-
-  return result;
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Performs the simulation of the packet losses, calls the error concealment funcs
- *    and copies the decoded images to the reference frame buffers of the decoders
- *
- *************************************************************************************
- */
-void UpdateDecoders()
-{
-  int k;
-  for (k=0; k<params->NoOfDecoders; k++)
-  {
-    Build_Status_Map(decs->status_map); // simulates the packet losses
-    Error_Concealment(decs->decY_best[k], decs->status_map, decs->decref[k]); // for the moment error concealment is just a "copy"
-    // Move decoded frames to reference buffers: (at the decoders this is done
-    // without interpolation (upsampling) - upsampling is done while decoding
-    DecOneForthPix(decs->decY_best[k], decs->decref[k]);
-  }
-}
-/*!
- *************************************************************************************
- * \brief
- *    Copies one (reconstructed) image to the respective reference frame buffer
- *
- * \note
- *    This is used at the "many decoders in the encoder"
- * \param dY
- *    The reconstructed image
- * \param dref
- *    The reference buffer
- *************************************************************************************
- */
-static void DecOneForthPix(imgpel **dY, imgpel ***dref)
-{
-  int j, ref=IMG_NUMBER%img->buf_cycle;
-
-  for (j=0; j<img->height; j++)
-    memcpy(dref[ref][j], dY[j], img->width * sizeof(imgpel));
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Gives the prediction residue for a 8x8 block
- *************************************************************************************
- */
-void compute_residue_b8block (int b8block, int i16mode) // if not INTRA16x16 it has to be -1
-{
-  int i,j;
-  int i0 = (b8block%2)<<3,   i1 = i0+8;
-  int j0 = (b8block/2)<<3,   j1 = j0+8;
-  imgpel  (*curr_mpr_16x16)[16][16] = img->mpr_16x16[0];
-  imgpel  (*curr_mpr)[16]           = img->mpr[0];
-
-
-  if (i16mode>=0)
-  {
-    for (i=i0; i<i1; i++)
-    for (j=j0; j<j1; j++)
-    {
-      decs->resY[j][i] = enc_picture->imgY[img->pix_y+j][img->pix_x+i] - curr_mpr_16x16[i16mode][j][i];
-    }
-  }
-  else
-  {
-    for (i=i0; i<i1; i++)
-    for (j=j0; j<j1; j++)
-    {
-      decs->resY[j][i] = enc_picture->imgY[img->pix_y+j][img->pix_x+i] - curr_mpr[j][i];
-    }
-  }
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Gives the prediction residue for a macroblock
- *************************************************************************************
- */
-void compute_residue_mb (int i16mode)
-{
-  compute_residue_b8block (0, i16mode);
-  compute_residue_b8block (1, i16mode);
-  compute_residue_b8block (2, i16mode);
-  compute_residue_b8block (3, i16mode);
-}
-
-
-/*!
- *************************************************************************************
- * \brief
- *    Builds a random status map showing whether each MB is received or lost, based
- *    on the packet loss rate and the slice structure.
- *
- * \param s_map
- *    The status map to be filled
- *************************************************************************************
- */
-static void Build_Status_Map(byte **s_map)
-{
-  int i,j,slice=-1,mb=0,jj,ii,packet_lost=0;
-
-  jj = img->height/MB_BLOCK_SIZE;
-  ii = img->width/MB_BLOCK_SIZE;
-
-  for (j=0 ; j<jj; j++)
-  for (i=0 ; i<ii; i++)
-  {
-    if (!params->slice_mode || img->mb_data[mb].slice_nr != slice) /* new slice */
-    {
-      packet_lost=0;
-      if ((double)rand()/(double)RAND_MAX*100 < params->LossRateC)   packet_lost += 3;
-      if ((double)rand()/(double)RAND_MAX*100 < params->LossRateB)   packet_lost += 2;
-      if ((double)rand()/(double)RAND_MAX*100 < params->LossRateA)   packet_lost  = 1;
-      slice++;
-    }
-    if (!packet_lost)
-    {
-      s_map[j][i]=0;  //! Packet OK
-    }
-    else
-    {
-      s_map[j][i]=packet_lost;
-      if(params->partition_mode == 0)  s_map[j][i]=1;
-    }
-    mb++;
-  }
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Performs some sort of error concealment for the areas that are lost according
- *    to the status_map
- *
- * \param inY
- *    Error concealment is performed on this frame imY[][]
- * \param s_map
- *    The status map shows which areas are lost.
- * \param refY
- *    The set of reference frames - may be used for the error concealment.
- *************************************************************************************
- */
-static void Error_Concealment(imgpel **inY, byte **s_map, imgpel ***refY)
-{
-  int mb_y, mb_x, mb_h, mb_w;
-  mb_h = img->height/MB_BLOCK_SIZE;
-  mb_w = img->width/MB_BLOCK_SIZE;
-
-  for (mb_y=0; mb_y < mb_h; mb_y++)
-  for (mb_x=0; mb_x < mb_w; mb_x++)
-  {
-    if (s_map[mb_y][mb_x])   
-      Conceal_Error(inY, mb_y, mb_x, refY, s_map);
-  }
-}
-
-/*!
- *************************************************************************************
- * \brief
- *    Copies a certain MB (mb_y,mb_x) of the frame inY[][] from the previous frame.
- *    For the time there is no better EC...
- *************************************************************************************
- */
-static void Conceal_Error(imgpel **inY, int mb_y, int mb_x, imgpel ***refY, byte **s_map)
-{
-  int i,j,block_x, block_y;
-  int ref_inx = (IMG_NUMBER-1)%img->num_ref_frames;
-  int pos_y = mb_y*MB_BLOCK_SIZE, pos_x = mb_x*MB_BLOCK_SIZE;
-  int mv[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE];
-  int resY[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
-  int copy  = (decs->dec_mb_mode[mb_y][mb_x]==0 && (img->type==P_SLICE || (img->type==B_SLICE && img->nal_reference_idc>0)));
-  int inter = (((decs->dec_mb_mode[mb_y][mb_x]>=1 && decs->dec_mb_mode[mb_y][mb_x]<=3) || decs->dec_mb_mode[mb_y][mb_x]==P8x8) && (img->type==P_SLICE || (img->type==B_SLICE && img->nal_reference_idc>0)));
-  short ***tmp_mv = enc_picture->mv[LIST_0];
-
-  switch(s_map[mb_y][mb_x])
-  {
-  case 1: //! whole slice lost (at least partition A lost)
-    if (img->type!=I_SLICE)
-    {
-      for (j=0;j<MB_BLOCK_SIZE;j++)
-        for (i=0;i<MB_BLOCK_SIZE;i++)
-          inY[pos_y+j][pos_x+i] = refY[ref_inx][pos_y+j][pos_x+i];
-    }
-    else
-    {
-      for (j=0;j<MB_BLOCK_SIZE;j++)
-        for (i=0;i<MB_BLOCK_SIZE;i++)
-          inY[pos_y+j][pos_x+i] = 127;
-    }
-    break;
-  case 5: //! partition B and partition C lost
-
-    //! Copy motion vectors
-    for (block_y=0; block_y<BLOCK_MULTIPLE; block_y++)
-      for (block_x=0; block_x<BLOCK_MULTIPLE; block_x++)
-        for (i=0;i<2;i++)
-          mv[i][block_y][block_x]=tmp_mv[mb_y*BLOCK_SIZE+block_y][mb_x*BLOCK_SIZE+block_x+4][i];
-
-    //! Residue ist set to zero
-    for(i=0;i<MB_BLOCK_SIZE;i++)
-      for(j=0;j<MB_BLOCK_SIZE;j++)
-        resY[j][i]=0;
-
-    //! not first frame
-    if (img->type!=I_SLICE)
-    {
-      //! if copy mb
-      if (copy)
-      {
-        for (j=0;j<MB_BLOCK_SIZE;j++)
-          for (i=0;i<MB_BLOCK_SIZE;i++)
-            inY[pos_y+j][pos_x+i] = refY[ref_inx][pos_y+j][pos_x+i];
-      }
-      //! if inter mb
-      else if (inter)
-      {
-        for (block_y = mb_y*BLOCK_SIZE ; block_y < (mb_y*BLOCK_SIZE + BLOCK_MULTIPLE) ; block_y++)
-          for (block_x = mb_x*BLOCK_SIZE ; block_x < (mb_x*BLOCK_SIZE + BLOCK_MULTIPLE) ; block_x++)
-          {
-            Get_Reference_Block(refY[ref_inx],
-                                block_y, block_x,
-                                mv[0][block_y - mb_y*BLOCK_SIZE][block_x - mb_x*BLOCK_SIZE],
-                                mv[1][block_y - mb_y*BLOCK_SIZE][block_x - mb_x*BLOCK_SIZE],
-                                decs->RefBlock);
-            for (j=0;j<BLOCK_SIZE;j++)
-              for (i=0;i<BLOCK_SIZE;i++)
-              {
-                inY[block_y*BLOCK_SIZE + j][block_x*BLOCK_SIZE + i] = decs->RefBlock[j][i];
-              }
-          }
-      }
-      else //intra; up to now only copy mb, may integrate nokia EC
-      {
-        for (j=0;j<MB_BLOCK_SIZE;j++)
-          for (i=0;i<MB_BLOCK_SIZE;i++)
-            inY[pos_y+j][pos_x+i] = refY[ref_inx][pos_y+j][pos_x+i];
-      }
-    }
-    else //! first frame; up to now set value to grey, may integrate nokia EC
-    {
-      for (j=0;j<MB_BLOCK_SIZE;j++)
-        for (i=0;i<MB_BLOCK_SIZE;i++)
-          inY[pos_y+j][pos_x+i] = 127;
-    }
-    break;
-  case 3: //! Partition C lost
-    if(img->type!=I_SLICE)
-    {
-      //! Copy motion vectors
-      for (block_y=0; block_y<BLOCK_MULTIPLE; block_y++)
-        for (block_x=0; block_x<BLOCK_MULTIPLE; block_x++)
-          for (i=0;i<2;i++)
-            mv[i][block_y][block_x]=tmp_mv[mb_y*BLOCK_SIZE+block_y][mb_x*BLOCK_SIZE+block_x+4][i];
-
-      //! Residue ist set to zero
-      for(i=0;i<MB_BLOCK_SIZE;i++)
-        for(j=0;j<MB_BLOCK_SIZE;j++)
-          resY[j][i]=0;
-
-      //! if copy mb
-      if (copy)
-      {
-        for (j=0;j<MB_BLOCK_SIZE;j++)
-          for (i=0;i<MB_BLOCK_SIZE;i++)
-            inY[pos_y+j][pos_x+i] = refY[ref_inx][pos_y+j][pos_x+i];
-      }
-      //! if inter mb
-      else if (inter)
-      {
-        for (block_y = mb_y*BLOCK_SIZE ; block_y < (mb_y*BLOCK_SIZE + BLOCK_MULTIPLE) ; block_y++)
-          for (block_x = mb_x*BLOCK_SIZE ; block_x < (mb_x*BLOCK_SIZE + BLOCK_MULTIPLE) ; block_x++)
-            {
-              Get_Reference_Block(refY[ref_inx],
-                                  block_y, block_x,
-                                  mv[0][block_y - mb_y*BLOCK_SIZE][block_x - mb_x*BLOCK_SIZE],
-                                  mv[1][block_y - mb_y*BLOCK_SIZE][block_x - mb_x*BLOCK_SIZE],
-                                  decs->RefBlock);
-              for (j=0;j<BLOCK_SIZE;j++)
-                for (i=0;i<BLOCK_SIZE;i++)
-                {
-                  inY[block_y*BLOCK_SIZE + j][block_x*BLOCK_SIZE + i] = decs->RefBlock[j][i];
-                }
-            }
-      }
-    }
-    break;
-  case 2: //! Partition B lost
-    if(img->type!=I_SLICE)
-    {
-      if(!inter)
-      {
-        for (j=0;j<MB_BLOCK_SIZE;j++)
-          for (i=0;i<MB_BLOCK_SIZE;i++)
-            inY[pos_y+j][pos_x+i] = refY[ref_inx][pos_y+j][pos_x+i];
-      }
-    }
-    else //! first frame; up to now set value to grey, may integrate nokia EC
-    {
-      for (j=0;j<MB_BLOCK_SIZE;j++)
-        for (i=0;i<MB_BLOCK_SIZE;i++)
-          inY[pos_y+j][pos_x+i] = 127;
-    }
-    break;
-  } //! End Switch
-}
diff --git a/lencod/src/errdo.c b/lencod/src/errdo.c
new file mode 100644
index 0000000..4e51bec
--- /dev/null
+++ b/lencod/src/errdo.c
@@ -0,0 +1,580 @@
+
+/*!
+ *************************************************************************************
+ * \file errdo.c
+ *
+ * \brief
+ *    Contains functions that implement the "decoders in the encoder" concept for the
+ *    rate-distortion optimization with losses.
+ * \date
+ *    October 22nd, 2001
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and
+ *    affiliation details)
+ *    - Dimitrios Kontopodis                    <dkonto@eikon.tum.de>
+ *    Code revamped July 2008 by:
+ *    - Peshala Pahalawatta (ppaha@dolby.com)
+ *************************************************************************************
+ */
+
+#include "global.h"
+#include "refbuf.h"
+#include "image.h"
+#include "errdo.h"
+#include "errdo_mc_prediction.h"
+
+static StorablePicture* find_nearest_ref_picture(int poc);
+static void copy_conceal_mb (StorablePicture *enc_pic, ImageParameters* image, int decoder, int mb_error, Macroblock* currMB, StorablePicture* refPic);
+static void get_predicted_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, Macroblock* currMB);
+static void add_residue     (StorablePicture *enc_pic, int decoder, int pl, int block8x8, int x_size, int y_size);
+static void Build_Status_Map(byte **s_map);
+
+extern void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***);
+
+/*!
+**************************************************************************************
+* \brief 
+*      Decodes one macroblock for error resilient RDO.  
+*    Currently does not support:
+*    1) B coded pictures
+*    2) Chroma components
+*    3) Potential error propagation due to intra prediction
+*    4) Field coding
+**************************************************************************************
+*/
+void decode_one_mb (ImageParameters *image, StorablePicture *enc_pic, int decoder, Macroblock* currMB)
+{
+  int i0, j;
+  static imgpel** curComp;
+  static imgpel** oldComp;
+
+  if (currMB->mb_type > P8x8) //Intra MB
+  {
+    curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
+    oldComp = &enc_pic->p_curr_img[image->pix_y];
+    i0 = image->pix_x;
+    for (j = 0; j < MB_BLOCK_SIZE; j++)
+    {
+      memcpy(&(curComp[j][i0]), &(oldComp[j][i0]), MB_BLOCK_SIZE*sizeof(imgpel));
+    }
+  }
+  else if (currMB->mb_type == 0)
+  {
+    get_predicted_mb(enc_pic, image, decoder, currMB);
+    curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
+    for(j = 0; j < image->mb_size[0][1]; j++)
+    {                
+      memcpy(&(curComp[j][image->pix_x]), &(image->mb_pred[0][j][0]), image->mb_size[0][0] * sizeof(imgpel));
+    }
+  }
+  else 
+  {
+    get_predicted_mb(enc_pic, image, decoder, currMB);
+    add_residue(enc_pic, decoder, PLANE_Y, 0, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
+  }
+}
+
+/*!
+**************************************************************************************
+* \brief 
+*      Finds predicted macroblock values 
+*   and copies them to img->mb_pred[0][][]
+*   Requires img->all_mv, enc_picture->motion.ref_idx to be correct for current
+*   macroblock.
+**************************************************************************************
+*/
+static void get_predicted_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, Macroblock* currMB)
+{
+  int i,j,k;
+  int block_size_x, block_size_y;
+  int mv_mode, pred_dir;
+  int list_offset   = 0; //For now
+  int curr_mb_field = 0; //For now
+  static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
+  int block8x8;
+  int k_start, k_end, k_inc;
+
+  if (!currMB->mb_type)
+  {
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = MB_BLOCK_SIZE;
+    pred_dir = LIST_0;
+
+    perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, 0, 0, list_offset, block_size_x, block_size_y, curr_mb_field);
+  }
+  else if (currMB->mb_type == 1)
+  {
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = MB_BLOCK_SIZE;
+    pred_dir = currMB->b8pdir[0];   
+
+    perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 1, 0, 0, 0, list_offset, block_size_x, block_size_y, curr_mb_field);
+  }
+  else if (currMB->mb_type == 2)
+  {   
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = 8;    
+
+    for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
+    {
+      pred_dir = currMB->b8pdir[block8x8];
+      perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 2, 0, 0, block8x8, list_offset, block_size_x, block_size_y, curr_mb_field);
+    }
+  }
+  else if (currMB->mb_type == 3)
+  {   
+    block_size_x = 8;
+    block_size_y = 16;
+
+    for (block8x8 = 0; block8x8 < 2; block8x8++)
+    {
+      i = block8x8<<1;
+      j = 0;      
+      pred_dir = currMB->b8pdir[block8x8];
+      assert (pred_dir<=2);
+      perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 3, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
+    }
+  }
+  else //Need to change to support B slices.
+  {
+    for (block8x8 = 0; block8x8 < 4; block8x8++)
+    {
+      mv_mode  = currMB->b8mode[block8x8];
+      pred_dir = currMB->b8pdir[block8x8];
+
+      if ( mv_mode != 0 )
+      {
+        k_start = (block8x8 << 2);
+        k_inc = (mv_mode == 5) ? 2 : 1;
+        k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);
+
+        block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
+        block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;
+
+        for (k = k_start; k < k_end; k += k_inc)
+        {
+          i =  (decode_block_scan[k] & 3);
+          j = ((decode_block_scan[k] >> 2) & 3);
+          perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, mv_mode, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
+        }        
+      }
+    }
+  }
+}
+
+
+/*!
+**************************************************************************************
+* \brief 
+*      Decodes one 8x8 partition for error resilient RDO.  
+*    Currently does not support:
+*    1) B coded pictures
+*    2) Chroma components
+*    3) Potential error propagation due to intra prediction
+*    4) Field coding
+**************************************************************************************
+*/
+void decode_one_b8block (ImageParameters *image, StorablePicture *enc_pic, int decoder, int mbmode, int block8x8, short mv_mode, short b8ref) //b8ref may not be necessary any more.
+{
+  int i,j,k;
+  int block_size_x, block_size_y;
+  int i0 = (block8x8 & 0x01)<<3;
+  int j0 = (block8x8 >> 1)<<3,   j1 = j0+8;
+  int list_offset = 0;
+  int curr_mb_field = 0;
+  imgpel **curComp;
+  imgpel **oldComp;
+  int pred_dir;
+  int k_start, k_end, k_inc;
+  static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
+
+  if (mv_mode > 8)  //Intra
+  {
+    for(j = j0; j < j1; j++)
+    {
+      curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
+      oldComp = &enc_pic->p_curr_img[image->pix_y];
+      memcpy(&(curComp[j][i0]), &(oldComp[j][i0]), sizeof(imgpel)*8);
+    }
+  }
+  else
+  {
+    pred_dir = 0;
+
+    k_start = (block8x8 << 2);
+    k_inc = (mv_mode == 5) ? 2 : 1;
+    k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);
+
+    block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
+    block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;
+
+    for (k = k_start; k < k_end; k += k_inc)
+    {
+      i =  (decode_block_scan[k] & 3);
+      j = ((decode_block_scan[k] >> 2) & 3);
+      perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, mv_mode, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
+    }        
+
+    add_residue(enc_pic, decoder, PLANE_Y, block8x8, 8, 8);
+  }
+}
+
+/*!
+**************************************************************************************
+* \brief 
+*      Add residual to motion predicted block
+**************************************************************************************
+*/
+static void add_residue (StorablePicture *enc_pic, int decoder, int pl, int block8x8, int x_size, int y_size) 
+{
+  int i,j;
+  int i0 = (block8x8 & 0x01)<<3, i1 = i0 + x_size;
+  int j0 = (block8x8 >> 1)<<3,   j1 = j0 + y_size;
+
+  imgpel **p_dec_img  = &enc_pic->p_dec_img[pl][decoder][img->pix_y];
+  int (*res_img)[16]  = decs->res_img[0];
+  imgpel (*mpr)[16]   = img->mb_pred[pl];
+
+
+  for (j = j0; j < j1; j++)
+  {
+    for (i = i0; i < i1; i++)
+    {
+      p_dec_img[j][img->pix_x+i] = iClip3(0, img->max_imgpel_value_comp[pl], (mpr[j][i] + res_img[j][i])); 
+    } 
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Performs the simulation of the packet losses, calls the error concealment funcs
+ *    and copies the decoded images to the reference frame buffers of the decoders
+ *
+ *************************************************************************************
+ */
+void UpdateDecoders(InputParameters *params, ImageParameters *image, StorablePicture *enc_pic)
+{
+  int k;
+  for (k = 0; k < params->NoOfDecoders; k++)
+  {
+    Build_Status_Map(enc_pic->mb_error_map[k]); // simulates the packet losses
+    error_conceal_picture(image, enc_pic, k); 
+    DeblockFrame (image, enc_pic->p_dec_img[0][k], NULL);
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Initialize error concealment function
+ *    (Currently only copy concealment is implemented. Can extend to other concealment
+ *    types when available.)
+ *
+ *************************************************************************************
+ */
+void init_error_conceal(int concealment_type)
+{
+  error_conceal_picture = copy_conceal_picture;
+}
+
+/*!
+**************************************************************************************
+* \brief 
+*      Finds predicted macroblock values for error concealment
+*   and copies them to img->mb_pred[0][][]
+*   Requires enc_picture->motion.mv and enc_picture->motion.ref_idx to be correct for 
+*   current picture.
+**************************************************************************************
+*/
+static void get_predicted_concealment_mb(StorablePicture* enc_pic, ImageParameters* image, int decoder, Macroblock* currMB)
+{
+  int i,j,k;
+  int block_size_x, block_size_y;
+  int mv_mode, pred_dir;
+  static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
+  int block8x8;
+  int k_start, k_end, k_inc;
+
+  if (!currMB->mb_type)
+  {
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = MB_BLOCK_SIZE;
+    pred_dir = LIST_0;
+
+    perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, block_size_x, block_size_y);
+  }
+  else if (currMB->mb_type == 1)
+  {
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = MB_BLOCK_SIZE;
+    pred_dir = currMB->b8pdir[0];   
+
+    perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, block_size_x, block_size_y);
+  }
+  else if (currMB->mb_type == 2)
+  {   
+    block_size_x = MB_BLOCK_SIZE;
+    block_size_y = 8;    
+
+    for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
+    {
+      pred_dir = currMB->b8pdir[block8x8];
+      perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, block8x8, block_size_x, block_size_y);
+    }
+  }
+  else if (currMB->mb_type == 3)
+  {   
+    block_size_x = 8;
+    block_size_y = 16;
+
+    for (block8x8 = 0; block8x8 < 2; block8x8++)
+    {
+      i = block8x8<<1;
+      j = 0;      
+      pred_dir = currMB->b8pdir[block8x8];
+      assert (pred_dir<=2);
+      perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, i, j, block_size_x, block_size_y);
+    }
+  }
+  else //Need to change to support B slices.
+  {
+    for (block8x8 = 0; block8x8 < 4; block8x8++)
+    {
+      mv_mode  = currMB->b8mode[block8x8];
+      pred_dir = currMB->b8pdir[block8x8];
+
+      if ( mv_mode != 0 )
+      {
+        k_start = (block8x8 << 2);
+        k_inc = (mv_mode == 5) ? 2 : 1;
+        k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);
+
+        block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
+        block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;
+
+        for (k = k_start; k < k_end; k += k_inc)
+        {
+          i =  (decode_block_scan[k] & 3);
+          j = ((decode_block_scan[k] >> 2) & 3);
+          perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, i, j, block_size_x, block_size_y);
+        }        
+      }
+    }
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Performs copy error concealment for macroblocks with errors.
+ *  Note: Currently assumes that the reference picture lists remain the same for all 
+ *        slices of a picture. 
+ *  
+ *************************************************************************************
+ */
+void copy_conceal_picture(ImageParameters *image, StorablePicture *enc_pic, int decoder)
+{
+  unsigned int mb;
+  Macroblock* currMB;
+  int mb_error;
+  byte** mb_error_map = enc_pic->mb_error_map[decoder];
+  StorablePicture* refPic;
+
+  refPic = find_nearest_ref_picture(enc_pic->poc); //Used for concealment if actual reference pic is not known.
+
+  for (mb = 0; mb < image->PicSizeInMbs; mb++)
+  {
+    image->mb_x = PicPos[mb][0];
+    image->mb_y = PicPos[mb][1];
+    mb_error = mb_error_map[image->mb_y][image->mb_x];
+    if (mb_error)
+    {
+      currMB = &image->mb_data[mb];
+      image->block_x = image->mb_x << 2;
+      image->block_y = image->mb_y << 2;
+      image->pix_x   = image->block_x << 2;
+      image->pix_y   = image->block_y << 2;
+      copy_conceal_mb(enc_pic, image, decoder, mb_error, currMB, refPic);
+    }
+  }
+}
+
+/******************************************************************************************
+*
+* Perform copy error concealment for macroblock.
+*   
+*******************************************************************************************
+*/
+static void copy_conceal_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, int mb_error, Macroblock* currMB, StorablePicture* refPic)
+{
+  int j, i0 = img->pix_x;
+  imgpel** concealed_img = &(enc_pic->p_dec_img[0][decoder][image->pix_y]);
+  imgpel** ref_img;
+
+  if (mb_error == 1 || (mb_error != 3 && currMB->mb_type > P8x8)) //All partitions lost, or intra mb lost
+  {
+    if (refPic != NULL) //Use nearest reference picture for concealment
+    {
+      ref_img = &(refPic->p_dec_img[0][decoder][img->pix_y]);
+      for (j = 0; j < MB_BLOCK_SIZE; j++)
+      {
+        memcpy(&(concealed_img[j][i0]), &(ref_img[j][i0]), sizeof(imgpel)*MB_BLOCK_SIZE);
+      }
+    }
+    else //No ref picture available
+    {
+      for (j = 0; j < MB_BLOCK_SIZE; j++)
+      {
+        memset(&(concealed_img[j][i0]), 128, sizeof(imgpel)*MB_BLOCK_SIZE); //Only reliable if sizeof(imgpel) = 1
+      }
+    }
+  }
+  else if (mb_error != 2 && image->type == P_SLICE && currMB->mb_type && currMB->mb_type < P8x8) //Only partition 3 lost, and P macroblock and not skip
+  {
+    get_predicted_concealment_mb(enc_pic, image, decoder, currMB);
+    for(j = 0; j < MB_BLOCK_SIZE; j++)
+    {                
+      memcpy(&(concealed_img[j][i0]), &(image->mb_pred[j][0]), MB_BLOCK_SIZE * sizeof(imgpel));
+    }
+  }
+}
+
+/******************************************************************************************
+*
+*  Finds reference picture with nearest POC to current picture to use for error concealment
+*   
+*******************************************************************************************
+*/
+static StorablePicture* find_nearest_ref_picture(int poc)
+{
+  unsigned int i;
+  int min_poc_diff = 1000;
+  int poc_diff;
+  StorablePicture* refPic = NULL;
+
+  for (i = 0; i < dpb.ref_frames_in_buffer; i++)
+  {
+    if (dpb.fs_ref[i]->is_used==3)
+    {
+      if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
+      {
+        poc_diff = iabs(dpb.fs_ref[i]->frame->poc - poc);
+        if (poc_diff < min_poc_diff)
+        {
+          refPic = dpb.fs_ref[i]->frame;
+          min_poc_diff = poc_diff;
+        }
+      }
+    }
+  }
+  return refPic;
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Gives the prediction residue for a block
+ *************************************************************************************
+ */
+void compute_residue_block (ImageParameters *image, imgpel **imgY, int res_img[16][16], imgpel mb_pred[16][16], int b8block, int block_size) 
+{
+  int i,j;
+  int i0 = (b8block & 0x01)<<3,   i1 = i0+block_size;
+  int j0 = (b8block >> 1)<<3,     j1 = j0+block_size;
+  //imgpel  (*mb_pred)[16]        = (i16mode >= 0) ? image->mpr_16x16[0][i16mode] : image->mb_pred[0];;
+
+  for (i = i0; i < i1; i++)
+  {
+    for (j = j0; j < j1; j++)
+    {
+      res_img[j][i] = (int)imgY[j][image->pix_x + i] - mb_pred[j][i];
+    } 
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Stores the pel values for the current best mode.
+ *************************************************************************************
+ */
+void errdo_store_best_block(ImageParameters* image, imgpel*** mbY, imgpel*** dec_img, int i0, int j0, int block_size)
+{
+  int j, k;
+  int i = image->pix_x + i0;
+  int j1 = j0 + block_size;
+  
+  for (k = 0; k < params->NoOfDecoders; k++)
+  {
+    for (j = j0; j < j1; j++)
+    {
+      memcpy(&mbY[k][j][i0], &dec_img[k][image->pix_y + j][i], block_size * sizeof(imgpel));
+    }
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Restores the pel values from the current best 8x8 mode.
+ *************************************************************************************
+ */
+void errdo_get_best_block(ImageParameters* image, imgpel*** dec_img, imgpel*** mbY, int j0, int block_size)
+{
+  int j, k;
+  int j1 = j0 + block_size;
+
+  for (k = 0; k < params->NoOfDecoders; k++)
+  {
+    for (j = j0; j < j1; j++)
+    {
+      memcpy(&dec_img[k][image->pix_y + j][image->pix_x], mbY[k][j], block_size * sizeof(imgpel));
+    }
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Builds a random status map showing whether each MB is received or lost, based
+ *    on the packet loss rate and the slice structure.
+ *
+ * \param s_map
+ *    The status map to be filled
+ *************************************************************************************
+ */
+static void Build_Status_Map(byte **s_map)
+{
+  int i,j,slice=-1,mb=0,jj,ii,packet_lost=0;
+
+  jj = img->height/MB_BLOCK_SIZE;
+  ii = img->width/MB_BLOCK_SIZE;
+
+  for (j = 0; j < jj; j++)
+  {
+    for (i = 0; i < ii; i++)
+    {
+      if (!params->slice_mode || img->mb_data[mb].slice_nr != slice) /* new slice */
+      {
+        packet_lost=0;
+        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateC)   packet_lost += 3;
+        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateB)   packet_lost += 2;
+        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateA)   packet_lost  = 1;
+        slice++;
+      }
+      if (!packet_lost)
+      {
+        s_map[j][i]=0;  //! Packet OK
+      }
+      else
+      {
+        s_map[j][i]=packet_lost;
+        if(params->partition_mode == 0)  s_map[j][i]=1;
+      }
+      mb++;
+    }
+  }
+}
+
diff --git a/lencod/src/errdo_mc_prediction.c b/lencod/src/errdo_mc_prediction.c
new file mode 100644
index 0000000..5064a94
--- /dev/null
+++ b/lencod/src/errdo_mc_prediction.c
@@ -0,0 +1,1295 @@
+/*!
+ *************************************************************************************
+ * \file decoder_mc_prediction.c
+ *
+ * \brief
+ *    Functions for motion compensated prediction
+ *
+ * \author
+ *      Main contributors (see contributors.h for copyright, 
+ *                         address and affiliation details)
+ *      - Alexis Michael Tourapis  <alexismt@ieee.org>
+ *      - Modified for encoder from ldecod/src/mc_prediction.c 
+ *          by Peshala V. Pahalawatta <pesh@ieee.org>
+ *************************************************************************************
+ */
+#include "global.h"
+#include "mbuffer.h"
+#include "mb_access.h"
+#include "macroblock.h"
+#include "errdo_mc_prediction.h"
+
+//extern StorablePicture *no_reference_picture;
+
+#if defined(USEMMX) 
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER) // ICC  
+__declspec(align(16)) imgpel tmp_block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
+__declspec(align(16)) imgpel tmp_block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
+# else  
+imgpel tmp_block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE]      __attribute__ ((aligned (16)));
+imgpel tmp_block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE]      __attribute__ ((aligned (16)));
+# endif
+#else
+imgpel tmp_block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE];     //!< l0 prediction
+imgpel tmp_block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE];     //!< l1 prediction
+#endif
+
+static const int COEF[6] = { 1, -5, 20, 20, -5, 1 };
+/*!
+ ************************************************************************
+ * \brief
+ *    block single list prediction
+ ************************************************************************
+ */
+static inline void mc_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+                    int ver_block_size, 
+                    int hor_block_size,
+                    int ioff,
+                    imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE])
+{
+  static int jj;
+
+  if (hor_block_size == MB_BLOCK_SIZE)
+  {
+    memcpy(&(mb_pred[0][ioff]), &(block[0][0]), hor_block_size * ver_block_size * sizeof(imgpel));
+  }
+  else
+  {
+    for(jj = 0; jj < ver_block_size; jj++)
+    {
+      memcpy(&(mb_pred[jj][ioff]), &(block[jj][0]), hor_block_size * sizeof(imgpel));
+    }
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    block single list weighted prediction
+ ************************************************************************
+ */
+static inline void weighted_mc_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+                            int ver_block_size, 
+                            int hor_block_size,
+                            int ioff,
+                            imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
+                            int wp_scale,
+                            int wp_offset,
+                            int weight_denom,
+                            int color_clip)
+{
+  static int ii, jj;
+  static imgpel *mpr, *b0;
+  
+  for(jj=0;jj<ver_block_size;jj++)
+  {
+    mpr = &mb_pred[jj][ioff];
+    b0 = block[jj];
+    for(ii=0;ii<hor_block_size;ii++)
+      *(mpr++) = (imgpel) iClip1(color_clip, (rshift_rnd((wp_scale * *(b0++)), weight_denom)  + wp_offset ));
+  }
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    block biprediction
+ ************************************************************************
+ */
+static inline void bi_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE],  
+                                 imgpel block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
+                                 imgpel block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+                                 int ver_block_size, 
+                                 int hor_block_size,
+                                 int ioff)
+{
+  static int ii, jj;
+  static imgpel *mpr, *b0, *b1;
+
+  for(jj = 0;jj < ver_block_size;jj++)
+  {
+    mpr = &mb_pred[jj][ioff];
+    b0 = block_l0[jj];
+    b1 = block_l1[jj];
+    for(ii = 0; ii < hor_block_size;ii++)
+      *(mpr++) = (imgpel) rshift_rnd_sf((*(b0++) + *(b1++)), 1);
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    block weighted biprediction
+ ************************************************************************
+ */
+static inline void weighted_bi_prediction(imgpel mb_pred[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
+                                          imgpel block_l0[MB_BLOCK_SIZE][MB_BLOCK_SIZE], 
+                                          imgpel block_l1[MB_BLOCK_SIZE][MB_BLOCK_SIZE],
+                                          int ver_block_size, 
+                                          int hor_block_size,
+                                          int ioff,
+                                          int wp_scale_l0,
+                                          int wp_scale_l1,
+                                          int wp_offset,
+                                          int weight_denom,
+                                          int color_clip)
+{
+  static int ii, jj;
+  static imgpel *mpr, *b0, *b1;
+  
+  for(jj = 0; jj < ver_block_size; jj++)
+  {
+    mpr = &mb_pred[jj][ioff];    
+    b0  = block_l0[jj];
+    b1  = block_l1[jj];
+
+    for(ii=0;ii<hor_block_size;ii++)
+      *(mpr++) = (imgpel) iClip1(color_clip, (rshift_rnd((wp_scale_l0 * *(b0++) + wp_scale_l1 * *(b1++)), weight_denom) + wp_offset));
+  }
+}
+
+void get_block_luma(int decoder, ColorPlane pl, StorablePicture* dec_picture, StorablePicture *curr_ref, int x_pos, int y_pos, int hor_block_size, int ver_block_size, ImageParameters *img, imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE])
+{
+  static int tmp_res[21][21];
+  static int *tmp_line;
+  static imgpel *p0, *p1, *p2, *p3, *p4, *p5;
+  static int    *x0, *x1, *x2, *x3, *x4, *x5;  
+  
+  static imgpel **cur_imgY, *cur_lineY;
+  static int ipos_m2, ipos_m1, ipos, ipos_p1, ipos_p2, ipos_p3;
+  static imgpel *orig_line;
+  int tmp_pos;
+
+  int dx = (x_pos & 3), dy = (y_pos & 3);
+  int i, j, jj;
+  int shift_x  = dec_picture->size_x;
+  int maxold_x = dec_picture->size_x - 1;
+  int maxold_y = (dec_picture->motion.mb_field[img->current_mb_nr]) ? (dec_picture->size_y >> 1) - 1 : dec_picture->size_y - 1;
+  int result;
+  int pres_x;
+  int max_imgpel_value = img->max_imgpel_value_comp[pl];
+
+
+  if( IS_INDEPENDENT(params) )
+  {
+    cur_imgY = curr_ref->p_dec_img[img->colour_plane_id][decoder];
+  }
+  else
+  {
+    cur_imgY = curr_ref->p_dec_img[pl][decoder];
+  }
+
+  x_pos = x_pos >> 2;
+  y_pos = y_pos >> 2;
+
+  if ( (y_pos > 1) && (y_pos < maxold_y - 2 - ver_block_size) && (x_pos > 1) && (x_pos < maxold_x - 2 - hor_block_size))
+  {
+    cur_imgY = &cur_imgY[ y_pos];
+    if (dx == 0 && dy == 0)
+    {  /* fullpel position */
+      for (j = 0; j < ver_block_size; j++)
+      {        
+        memcpy(&(block[j][0]), &(cur_imgY[j][x_pos]), hor_block_size * sizeof(imgpel));
+      }
+    }
+    else
+    { /* other positions */
+
+      if (dy == 0)
+      { /* No vertical interpolation */
+        for (j = 0; j < ver_block_size; j++)
+        {
+          p0 = &cur_imgY[j][x_pos - 2];
+          p1 = p0 + 1;
+          p2 = p1 + 1;
+          p3 = p2 + 1;
+          p4 = p3 + 1;
+          p5 = p4 + 1;
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {        
+            result  = (*(p0++) + *(p5++)) * COEF[0]
+                    + (*(p1++) + *(p4++)) * COEF[1]
+                    + (*(p2++) + *(p3++)) * COEF[2];
+
+            *orig_line++ = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
+          }
+        }
+
+        if ((dx&1) == 1)
+        {          
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = &(cur_imgY[j][x_pos + (dx >> 1)]);
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + *(cur_lineY++) + 1 ) >> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dx == 0)
+      {  /* No horizontal interpolation */        
+        p0 = &(cur_imgY[ - 2][x_pos]);
+        for (j = 0; j < ver_block_size; j++)
+        {                  
+          p1 = p0 + shift_x;          
+          p2 = p1 + shift_x;
+          p3 = p2 + shift_x;
+          p4 = p3 + shift_x;
+          p5 = p4 + shift_x;
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*(p0++) + *(p5++)) * COEF[0]
+                    + (*(p1++) + *(p4++)) * COEF[1]
+                    + (*(p2++) + *(p3++)) * COEF[2];
+
+            *orig_line++ = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
+          }
+          p0 = p1 - hor_block_size;
+        }
+
+        if ((dy&1) == 1)
+        {
+          jj = (dy >> 1);
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = &(cur_imgY[jj++][x_pos]);
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + *(cur_lineY++) + 1 ) >> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dx == 2)
+      {  /* Vertical & horizontal interpolation */
+        jj = - 2;
+        for (j = 0; j < ver_block_size + 5; j++)
+        {
+          p0 = &cur_imgY[jj++][x_pos - 2];
+          p1 = p0 + 1;
+          p2 = p1 + 1;
+          p3 = p2 + 1;
+          p4 = p3 + 1;
+          p5 = p4 + 1;
+          orig_line = block[j];
+          tmp_line  = tmp_res[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {        
+            *(tmp_line++) = (*(p0++) + *(p5++)) * COEF[0]
+                          + (*(p1++) + *(p4++)) * COEF[1]
+                          + (*(p2++) + *(p3++)) * COEF[2];
+          }
+        }
+
+        for (j = 0; j < ver_block_size; j++)
+        {
+          x0 = tmp_res[j    ];
+          x1 = tmp_res[j + 1];
+          x2 = tmp_res[j + 2];
+          x3 = tmp_res[j + 3];
+          x4 = tmp_res[j + 4];
+          x5 = tmp_res[j + 5];
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*x0++ + *x5++) * COEF[0]
+                    + (*x1++ + *x4++) * COEF[1]
+                    + (*x2++ + *x3++) * COEF[2];
+
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+512)>>10));
+          }
+        }
+
+        if ((dy&1) == 1)
+        {
+          jj = 2 + (dy>>1);
+          for (j = 0; j < ver_block_size; j++)
+          {            
+            tmp_line  = tmp_res[jj++];
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dy == 2)
+      {  /* Horizontal & vertical interpolation */
+        p0 = &(cur_imgY[ -2][x_pos - 2]);
+        for (j = 0; j < ver_block_size; j++)
+        {                    
+          p1 = p0 + shift_x;
+          p2 = p1 + shift_x;
+          p3 = p2 + shift_x;
+          p4 = p3 + shift_x;
+          p5 = p4 + shift_x;
+          tmp_line  = tmp_res[j];
+
+          for (i = 0; i < hor_block_size + 5; i++)
+          {
+            *(tmp_line++)  = (*(p0++) + *(p5++)) * COEF[0]
+                           + (*(p1++) + *(p4++)) * COEF[1]
+                           + (*(p2++) + *(p3++)) * COEF[2];
+          }
+          p0 = p1 - (hor_block_size + 5);
+        }
+
+        for (j = 0; j < ver_block_size; j++)
+        {
+          orig_line = block[j];
+          x0 = tmp_res[j];
+          x1 = x0 + 1;
+          x2 = x1 + 1;
+          x3 = x2 + 1;
+          x4 = x3 + 1;
+          x5 = x4 + 1;
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*(x0++) + *(x5++)) * COEF[0]
+                    + (*(x1++) + *(x4++)) * COEF[1]
+                    + (*(x2++) + *(x3++)) * COEF[2];
+
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 512)>>10));
+          }
+        }
+
+        if ((dx&1) == 1)
+        {
+          for (j = 0; j < ver_block_size; j++)
+          {
+            tmp_line  = &tmp_res[j][2 + (dx>>1)];
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16)>>5))+1)>>1);
+              orig_line ++;
+            }
+          }
+        }
+      }
+      else
+      {  /* Diagonal interpolation */
+        jj = (dy == 1 ? 0 : 1);
+
+        for (j = 0; j < ver_block_size; j++)
+        {
+          p0 = &cur_imgY[jj++][x_pos - 2];
+          p1 = p0 + 1;
+          p2 = p1 + 1;
+          p3 = p2 + 1;
+          p4 = p3 + 1;
+          p5 = p4 + 1;
+
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {        
+            result  = (*(p0++) + *(p5++)) * COEF[0]
+                    + (*(p1++) + *(p4++)) * COEF[1]
+                    + (*(p2++) + *(p3++)) * COEF[2];
+
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
+          }
+        }
+
+        p0 = &(cur_imgY[-2][(dx == 1 ? x_pos : x_pos + 1)]);
+        for (j = 0; j < ver_block_size; j++)
+        {        
+          p1 = p0 + shift_x;
+          p2 = p1 + shift_x;
+          p3 = p2 + shift_x;
+          p4 = p3 + shift_x;
+          p5 = p4 + shift_x;
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*(p0++) + *(p5++)) * COEF[0]
+                    + (*(p1++) + *(p4++)) * COEF[1]
+                    + (*(p2++) + *(p3++)) * COEF[2];
+
+            *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((result + 16) >> 5)) + 1) >> 1);
+            orig_line++;
+          }
+          p0 = p1 - hor_block_size ;
+        }      
+      }
+    }
+  }
+  else // unsafe positions
+  {
+    if (dx == 0 && dy == 0)
+    {  /* fullpel position */
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_lineY = cur_imgY[iClip3(0, maxold_y, y_pos + j)];
+        orig_line = block[j];
+        for (i = 0; i < hor_block_size; i++)
+        {
+          *(orig_line++) = cur_lineY[iClip3(0, maxold_x, x_pos + i )];
+        }
+      }
+    }
+    else
+    { /* other positions */
+
+      if (dy == 0)
+      { /* No vertical interpolation */
+        tmp_pos = x_pos - 2;
+        for (i = 0; i < hor_block_size; i++)
+        {        
+          ipos_m2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_m1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p3 = iClip3(0, maxold_x, tmp_pos  );
+          tmp_pos -= 4;          
+
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = cur_imgY[iClip3(0,maxold_y,y_pos+j)];
+
+            result  = (cur_lineY[ipos_m2] + cur_lineY[ipos_p3]) * COEF[0];
+            result += (cur_lineY[ipos_m1] + cur_lineY[ipos_p2]) * COEF[1];
+            result += (cur_lineY[ipos   ] + cur_lineY[ipos_p1]) * COEF[2];
+
+            block[j][i] = (imgpel) iClip1(max_imgpel_value, ((result + 16)>>5));
+          }
+        }
+
+        if ((dx&1) == 1)
+        {
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = cur_imgY[iClip3(0,maxold_y,y_pos+j)];
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + cur_lineY[iClip3(0, maxold_x, x_pos + i + (dx >> 1))] + 1 ) >> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dx == 0)
+      {  /* No horizontal interpolation */
+        tmp_pos = y_pos - 2;
+        for (j = 0; j < ver_block_size; j++)
+        { 
+          p0 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p1 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p2 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p3 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p4 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p5 = cur_imgY[iClip3(0, maxold_y, tmp_pos  )];
+          
+          tmp_pos -= 4;
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            pres_x = iClip3(0,maxold_x,x_pos+i);
+
+            result  = (p0[pres_x] + p5[pres_x]) * COEF[0];
+            result += (p1[pres_x] + p4[pres_x]) * COEF[1];
+            result += (p2[pres_x] + p3[pres_x]) * COEF[2];
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+16)>>5));
+          }
+        }
+
+        if ((dy&1) == 1)
+        {
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = cur_imgY[iClip3(0,maxold_y,y_pos+j+(dy>>1))];
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + cur_lineY[iClip3(0, maxold_x, x_pos + i)] + 1 ) >> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dx == 2)
+      {  /* Vertical & horizontal interpolation */
+        tmp_pos = x_pos - 2;
+        for (i = 0; i < hor_block_size; i++)
+        {        
+          ipos_m2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_m1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p3 = iClip3(0, maxold_x, tmp_pos  );
+          tmp_pos -= 4;
+
+          for (j = 0; j < ver_block_size + 5; j++)
+          {
+            cur_lineY = cur_imgY[iClip3(0,maxold_y,y_pos + j - 2)];
+
+            tmp_res[j][i]  = (cur_lineY[ipos_m2] + cur_lineY[ipos_p3]) * COEF[0];
+            tmp_res[j][i] += (cur_lineY[ipos_m1] + cur_lineY[ipos_p2]) * COEF[1];
+            tmp_res[j][i] += (cur_lineY[ipos   ] + cur_lineY[ipos_p1]) * COEF[2];
+          }
+        }
+
+        for (j = 0; j < ver_block_size; j++)
+        {
+          x0 = tmp_res[j    ];
+          x1 = tmp_res[j + 1];
+          x2 = tmp_res[j + 2];
+          x3 = tmp_res[j + 3];
+          x4 = tmp_res[j + 4];
+          x5 = tmp_res[j + 5];
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*x0++ + *x5++) * COEF[0]
+                    + (*x1++ + *x4++) * COEF[1]
+                    + (*x2++ + *x3++) * COEF[2];
+
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result+512)>>10));
+          }
+        }
+
+        if ((dy&1) == 1)
+        {
+          for (j = 0; j < ver_block_size; j++)
+          {
+            tmp_line  = tmp_res[j + 2 + (dy>>1)];            
+            orig_line = block[j];
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16) >> 5)) + 1 )>>1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else if (dy == 2)
+      {  /* Horizontal & vertical interpolation */
+
+        tmp_pos = y_pos - 2;
+        for (j = 0; j < ver_block_size; j++)
+        {
+          p0 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p1 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p2 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p3 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p4 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p5 = cur_imgY[iClip3(0, maxold_y, tmp_pos  )];
+
+          tmp_pos -= 4;
+
+          for (i = 0; i < hor_block_size + 5; i++)
+          {
+            pres_x = iClip3(0,maxold_x, x_pos + i - 2);
+            result  = (p0[pres_x] + p5[pres_x])*COEF[0]
+                    + (p1[pres_x] + p4[pres_x])*COEF[1]
+                    + (p2[pres_x] + p3[pres_x])*COEF[2];
+            tmp_res[j][i] = result;
+          }
+        }
+
+        for (j = 0; j < ver_block_size; j++)
+        {
+          orig_line = block[j];
+          tmp_line  = tmp_res[j];
+          x0 = tmp_res[j];
+          x1 = x0 + 1;
+          x2 = x1 + 1;
+          x3 = x2 + 1;
+          x4 = x3 + 1;
+          x5 = x4 + 1;
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            result  = (*(x0++) + *(x5++)) * COEF[0]
+                    + (*(x1++) + *(x4++)) * COEF[1]
+                    + (*(x2++) + *(x3++)) * COEF[2];
+
+            *(orig_line++) = (imgpel) iClip1(max_imgpel_value, ((result + 512)>>10));
+          }
+        }
+
+        if ((dx&1) == 1)
+        {
+          for (j = 0; j < ver_block_size; j++)
+          {
+            tmp_line  = &tmp_res[j][2 + (dx>>1)];
+            orig_line = block[j];            
+            for (i = 0; i < hor_block_size; i++)
+            {
+              *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((*(tmp_line++) + 16)>>5)) + 1)>> 1);
+              orig_line++;
+            }
+          }
+        }
+      }
+      else
+      {  /* Diagonal interpolation */
+        tmp_pos = x_pos - 2;
+        for (i = 0; i < hor_block_size; i++)
+        {
+          ipos_m2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_m1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p1 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p2 = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p3 = iClip3(0, maxold_x, tmp_pos  );
+          tmp_pos -= 4;
+
+          for (j = 0; j < ver_block_size; j++)
+          {
+            cur_lineY = cur_imgY[iClip3(0,maxold_y,(dy == 1 ? y_pos+j : y_pos+j+1))];
+
+            result  = (cur_lineY[ipos_m2] + cur_lineY[ipos_p3]) * COEF[0];
+            result += (cur_lineY[ipos_m1] + cur_lineY[ipos_p2]) * COEF[1];
+            result += (cur_lineY[ipos   ] + cur_lineY[ipos_p1]) * COEF[2];
+
+            block[j][i] = (imgpel) iClip1(max_imgpel_value, ((result+16)>>5));
+          }
+        }
+
+        tmp_pos = y_pos - 2;
+        for (j = 0; j < ver_block_size; j++)
+        {      
+          p0 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p1 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p2 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p3 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p4 = cur_imgY[iClip3(0, maxold_y, tmp_pos++)];
+          p5 = cur_imgY[iClip3(0, maxold_y, tmp_pos  )];
+
+          tmp_pos -= 4;
+          orig_line = block[j];
+
+          for (i = 0; i < hor_block_size; i++)
+          {
+            pres_x = dx == 1 ? x_pos+i : x_pos+i+1;
+            pres_x = iClip3(0, maxold_x, pres_x);
+
+            result  = (p0[pres_x] + p5[pres_x]) * COEF[0];
+            result += (p1[pres_x] + p4[pres_x]) * COEF[1];
+            result += (p2[pres_x] + p3[pres_x]) * COEF[2];
+
+            *orig_line = (imgpel) ((*orig_line + iClip1(max_imgpel_value, ((result+16)>>5)) + 1 ) >> 1);
+            orig_line++;
+          }
+        }      
+      }
+    }
+  }
+}
+
+void get_block_chroma(int decoder, int uv, StorablePicture* dec_picture, StorablePicture *curr_ref, int x_pos, int y_pos, int hor_block_size, int ver_block_size, ImageParameters *img, imgpel block[MB_BLOCK_SIZE][MB_BLOCK_SIZE])
+{
+  int subpel_x    = img->mb_cr_size_x == 8 ? 7 : 3;
+  int subpel_y    = img->mb_cr_size_y == 8 ? 7 : 3;
+  int shiftpel_x  = img->mb_cr_size_x == 8 ? 3 : 2;
+  int shiftpel_y  = img->mb_cr_size_y == 8 ? 3 : 2;
+  int total_scale = shiftpel_x + shiftpel_y;
+
+  int dx = (x_pos & subpel_x);
+  int dy = (y_pos & subpel_y);
+  int dxcur = (subpel_x + 1 - dx);
+  int dycur = (subpel_y + 1 - dy);
+
+  int w00 = dxcur * dycur;
+  int w01 = dxcur * dy;
+  int w10 = dx * dycur;
+  int w11 = dx * dy;
+
+  int i, j;
+  int maxold_x = dec_picture->size_x_cr - 1;
+  int maxold_y = (dec_picture->motion.mb_field[img->current_mb_nr]) ? (dec_picture->size_y_cr >> 1) - 1 : dec_picture->size_y_cr - 1;
+  int result;
+  
+  static imgpel **cur_img, *blk_line;
+  static imgpel *cur_line, *cur_line_p1;
+  int tmp_pos;
+  static int ipos, ipos_p1;
+  int    max_imgpel_value = img->max_imgpel_value_comp[uv + 1];
+
+#if 0
+  if (curr_ref == no_reference_picture && img->framepoc < img->recovery_poc)
+  {
+    printf("list[ref_frame] is equal to 'no reference picture' before RAP\n");
+
+    /* fill the block with sample value 128 */
+    for (j = 0; j < ver_block_size; j++)
+      for (i = 0; i < hor_block_size; i++)
+        block[j][i] = 128;
+    return;
+  }
+#endif
+
+  cur_img = curr_ref->p_dec_img[uv+1][decoder];
+
+  x_pos = x_pos >> shiftpel_x;
+  y_pos = y_pos >> shiftpel_y;
+
+  if ((y_pos >= 0) && (y_pos < maxold_y - ver_block_size) && (x_pos >= 0) && (x_pos < maxold_x - hor_block_size))
+  {
+    if (dx == 0 && dy == 0)
+    {  /* fullpel position */
+      for (j = 0; j < ver_block_size; j++)
+      {        
+        memcpy(&(block[j][0]), &(cur_img[ y_pos + j ][x_pos]), hor_block_size * sizeof(imgpel));
+      }
+    }
+    else if (dx == 0)
+    { 
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = &cur_img[y_pos + j    ][x_pos];
+        cur_line_p1 = &cur_img[y_pos + j + 1][x_pos];
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          result = (w00 * *cur_line++ + w01 * *cur_line_p1++);
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }
+    }
+    else if (dy == 0)
+    { 
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = &cur_img[y_pos + j][x_pos];
+        cur_line_p1 = cur_line + 1;
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          result = (w00 * *cur_line++ + w10 * *cur_line_p1++);
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }
+    }
+    else
+    { /* other positions */
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = &cur_img[y_pos + j    ][x_pos];
+        cur_line_p1 = &cur_img[y_pos + j + 1][x_pos];
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          result  = (w00 * *(cur_line++) + w01 * *(cur_line_p1++));
+          result += (w10 * *(cur_line  ) + w11 * *(cur_line_p1  ));
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }
+    }
+  }
+  else // unsafe positions
+  {
+    if (dx == 0 && dy == 0)
+    {  /* fullpel position */
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line = cur_img[iClip3(0, maxold_y, y_pos + j)];
+        blk_line = block[j];
+        for (i = 0; i < hor_block_size; i++)
+        {
+          *(blk_line++) = cur_line[iClip3(0, maxold_x, x_pos + i )];
+        }
+      }
+    }
+    else if (dx == 0)
+    { 
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = cur_img[iClip3(0, maxold_y, y_pos + j)];
+        cur_line_p1 = cur_img[iClip3(0, maxold_y, y_pos + j + 1)];
+        tmp_pos = x_pos;
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+
+          result = (w00 * cur_line[ipos] + w01 * cur_line_p1[ipos]);
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }      
+    }
+    else if (dy == 0)
+    { 
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = cur_img[iClip3(0, maxold_y, y_pos + j)];
+        tmp_pos = x_pos;
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p1 = iClip3(0, maxold_x, tmp_pos  );
+
+          result = (w00 * cur_line[ipos   ] + w10 * cur_line[ipos_p1]);
+          *(blk_line++) = (imgpel)iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }      
+    }
+    else
+    { /* other positions */ 
+      for (j = 0; j < ver_block_size; j++)
+      {
+        cur_line    = cur_img[iClip3(0, maxold_y, y_pos + j)];
+        cur_line_p1 = cur_img[iClip3(0, maxold_y, y_pos + j + 1)];
+        tmp_pos = x_pos;
+        blk_line = block[j];
+
+        for (i = 0; i < hor_block_size; i++)
+        {
+          ipos    = iClip3(0, maxold_x, tmp_pos++);
+          ipos_p1 = iClip3(0, maxold_x, tmp_pos  );
+
+          result = (
+            w00 * cur_line   [ipos   ] + 
+            w10 * cur_line   [ipos_p1] +
+            w01 * cur_line_p1[ipos   ] +
+            w11 * cur_line_p1[ipos_p1]);
+          *(blk_line++) = (imgpel) iClip1(max_imgpel_value, rshift_rnd_sf(result, total_scale));
+        }
+      }      
+    }
+  }
+}
+
+#if 0
+void intra_cr_decoding(Macroblock *currMB, int yuv, ImageParameters *img, int smb)
+{
+  imgpel **curUV, *cur_img;
+  int (*m7UV)[16], *m7;
+  int uv;
+  int b8,b4;
+  int ioff, joff, ii, jj;
+
+  for(uv = 0; uv < 2; uv++)
+  {
+    Boolean lossless_qpprime = (Boolean) ((img->lossless_qpprime_flag == 1) &&((img->qp + dec_picture->chroma_qp_offset[uv] + img->bitdepth_chroma_qp_scale) == 0));
+    itrans_4x4 = (!lossless_qpprime) ? itrans4x4 : itrans4x4_ls;
+
+    curUV = dec_picture->imgUV[uv];
+    m7UV  = img->mb_rres[uv+1];
+    intrapred_chroma(img, currMB, uv);
+
+    if (!smb && (currMB->cbp >> 4))
+    {
+      for (b8 = 0; b8 < (img->num_uv_blocks); b8++)
+      {
+        for(b4 = 0; b4 < 4; b4++)
+        {
+          joff = subblk_offset_y[yuv][b8][b4];          
+          ioff = subblk_offset_x[yuv][b8][b4];          
+
+          itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
+
+          for(jj=joff; jj<joff + 4;jj++)
+          {
+            cur_img = &curUV[img->pix_c_y+jj][img->pix_c_x + ioff];
+            m7 = &m7UV[jj][ioff];
+
+            for(ii=0; ii<4;ii++)
+            {
+              *cur_img++ = (imgpel) *m7++;
+            }
+          }
+        }
+      }
+    }
+    else if ((currMB->cbp >> 4) == 0)
+    {
+      for (b8 = 0; b8 < (img->num_uv_blocks); b8++)
+      {
+        for(b4 = 0; b4 < 4; b4++)
+        {
+          joff = subblk_offset_y[yuv][b8][b4];
+          ioff = subblk_offset_x[yuv][b8][b4];          
+
+          for(jj = joff; jj < 4 + joff;jj++)
+            memcpy(&(curUV[img->pix_c_y + jj][img->pix_c_x + ioff]), &(img->mb_pred[uv + 1][jj][ioff]), BLOCK_SIZE * sizeof(imgpel));
+        }
+      }
+    }
+    else
+    {
+      itrans_sp_cr(img, uv);
+
+      for (joff  = 0; joff < 8; joff += 4)
+      {
+        for(ioff = 0; ioff < 8;ioff+=4)
+        {          
+          itrans_4x4(img, (ColorPlane) (uv + 1), ioff, joff);
+
+          for(jj = joff; jj < joff + 4; jj++)
+            for(ii = ioff; ii < ioff + 4; ii++)
+            {
+              curUV[img->pix_c_y+jj][ii + img->pix_c_x] = (imgpel) img->mb_rres[uv+1][jj][ii];
+            }
+        }
+      }
+    }
+  }
+}
+
+void prepare_direct_params(Macroblock *currMB, StorablePicture *dec_picture, ImageParameters *img, short pmvl0[2], short pmvl1[2],char *l0_rFrame, char *l1_rFrame)
+{
+  char l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR;
+  char l1_rFrameL, l1_rFrameU, l1_rFrameUL, l1_rFrameUR;
+  
+  PixelPos mb_left, mb_up, mb_upleft, mb_upright;
+
+  get4x4Neighbour(currMB, -1,  0, img->mb_size[IS_LUMA], &mb_left);
+  get4x4Neighbour(currMB,  0, -1, img->mb_size[IS_LUMA], &mb_up);
+  get4x4Neighbour(currMB, 16, -1, img->mb_size[IS_LUMA], &mb_upright);
+  get4x4Neighbour(currMB, -1, -1, img->mb_size[IS_LUMA], &mb_upleft);
+
+  if (!img->MbaffFrameFlag)
+  {
+    l0_rFrameL  = (char) (mb_left.available    ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]       : -1);
+    l0_rFrameU  = (char) (mb_up.available      ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x]           : -1);
+    l0_rFrameUL = (char) (mb_upleft.available  ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
+    l0_rFrameUR = (char) (mb_upright.available ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
+
+    l1_rFrameL  = (char) (mb_left.available     ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]      : -1);
+    l1_rFrameU  = (char) (mb_up.available       ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]          : -1);
+    l1_rFrameUL = (char) (mb_upleft.available  ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]   : -1);
+    l1_rFrameUR = (char) (mb_upright.available ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
+  }
+  else
+  {
+    if (currMB->mb_field)
+    {
+      l0_rFrameL = (char) (mb_left.available 
+        ? img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0
+        ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] 
+        : dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1);
+
+      l0_rFrameU = (char) (mb_up.available 
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0
+        ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] 
+        : dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1);
+
+       l0_rFrameUL = (char) (mb_upleft.available 
+         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0
+         ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1);
+
+       l0_rFrameUR = (char) (mb_upright.available 
+         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
+         ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL);
+
+       l1_rFrameL = (char) (mb_left.available 
+         ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1);
+
+       l1_rFrameU = (char) (mb_up.available 
+         ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1);
+
+       l1_rFrameUL = (char) (mb_upleft.available 
+         ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]  < 0 
+         ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2 : -1);
+
+       l1_rFrameUR = (char) (mb_upright.available 
+         ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0
+         ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] 
+         : dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL);
+    }
+    else
+    {
+      l0_rFrameL = (char) (mb_left.available 
+        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]  < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1);
+
+      l0_rFrameU = (char) (mb_up.available 
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1);
+
+      l0_rFrameUL = (char) (mb_upleft.available 
+        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
+
+      l0_rFrameUR = (char) (mb_upright.available 
+        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL);
+
+      l1_rFrameL = (char) (mb_left.available 
+        ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1);
+
+      l1_rFrameU = (char) (mb_up.available 
+        ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1);
+
+      l1_rFrameUL = (char) (mb_upleft.available 
+        ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 
+        : dec_picture->motion.ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1);
+
+      l1_rFrameUR = (char) (mb_upright.available 
+        ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 
+        ? dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1
+        : dec_picture->motion.ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL);
+    }
+  }
+
+  *l0_rFrame = (char) ((l0_rFrameL >= 0 && l0_rFrameU >= 0)  ? imin(l0_rFrameL,l0_rFrameU) : imax(l0_rFrameL,l0_rFrameU));
+  *l0_rFrame = (char) ((*l0_rFrame >= 0 && l0_rFrameUR >= 0) ? imin(*l0_rFrame,l0_rFrameUR): imax(*l0_rFrame,l0_rFrameUR));
+
+  *l1_rFrame = (char) ((l1_rFrameL >= 0 && l1_rFrameU >= 0)  ? imin(l1_rFrameL,l1_rFrameU) : imax(l1_rFrameL,l1_rFrameU));
+  *l1_rFrame = (char) ((*l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(*l1_rFrame,l1_rFrameUR): imax(*l1_rFrame,l1_rFrameUR));
+
+  if (*l0_rFrame >=0)
+    SetMotionVectorPredictor (img, currMB, pmvl0, *l0_rFrame, LIST_0, dec_picture->motion.ref_idx, dec_picture->motion.mv, 0, 0, 16, 16);
+
+  if (*l1_rFrame >=0)
+    SetMotionVectorPredictor (img, currMB, pmvl1, *l1_rFrame, LIST_1, dec_picture->motion.ref_idx, dec_picture->motion.mv, 0, 0, 16, 16);
+}
+
+void check_motion_vector_range(ImageParameters *img, short mv_x, short mv_y)
+{
+  if (mv_x > 8191 || mv_x < -8192)
+  {
+    fprintf(stderr,"ERROR! Horizontal motion vector %d is out of allowed range {-8192, 8191} in picture %d, macroblock %d\n", mv_x, img->number, img->current_mb_nr);
+    error("invalid stream: too big horizontal motion vector", 500);
+  }
+
+  if (mv_y > (img->max_mb_vmv_r - 1) || mv_y < (-img->max_mb_vmv_r))
+  {
+    fprintf(stderr,"ERROR! Vertical motion vector %d is out of allowed range {%d, %d} in picture %d, macroblock %d\n", mv_y, (-img->max_mb_vmv_r), (img->max_mb_vmv_r - 1), img->number, img->current_mb_nr);
+    error("invalid stream: too big vertical motion vector", 500);
+  }
+}
+#endif
+
+void perform_mc(int decoder, ColorPlane pl, StorablePicture *dec_picture, ImageParameters *img, int pred_dir, int l0_mode, int l1_mode, int i, int j, int list_offset, int block_size_x, int block_size_y, int curr_mb_field)
+{
+  static int vec1_x=0, vec1_y=0;
+#if 0
+  static int vec2_x=0, vec2_y=0;
+  static int vec1_y_cr = 0, vec2_y_cr = 0;
+  static int alpha_l0, alpha_l1, wp_offset;
+  int        max_imgpel_value = img->max_imgpel_value_comp[pl];
+#endif
+  static const int mv_mul = 16; // 4 * 4
+
+  
+  int i4   = img->block_x + i;
+  int j4   = img->block_y + j;
+  int ioff = (i << 2);
+  int joff = (j << 2);         
+  
+  assert (pred_dir<=2);
+
+  if (pred_dir != 2)
+  {
+    //===== Single List Prediction =====
+    short       ref_idx = dec_picture->motion.ref_idx[pred_dir][j4][i4];
+    //short       ref_idx_wp = ref_idx;
+    short      ***mv_array = img->all_mv[pred_dir][ref_idx][l0_mode];
+    StorablePicture **list = listX[list_offset + pred_dir];
+
+    //check_motion_vector_range(img, mv_array[j4][i4][0], mv_array[j4][i4][1]);
+
+    vec1_x = i4 * mv_mul + mv_array[j][i][0];
+    //vec1_y = (img->block_y_aff + j) * mv_mul + mv_array[j4][i4][1];
+    vec1_y = j4 * mv_mul + mv_array[j][i][1];
+
+    get_block_luma (decoder, pl, dec_picture, list[ref_idx], vec1_x, vec1_y, block_size_x, block_size_y, img, tmp_block_l0); 
+
+#if 0 //Currently not used
+    if (img->apply_weights)
+    {
+      if (curr_mb_field && ((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
+         (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))))
+      {
+        ref_idx_wp >>=1;
+      }
+
+      alpha_l0  = img->wp_weight[pred_dir][ref_idx_wp][0];
+      wp_offset = img->wp_offset[pred_dir][ref_idx_wp][0];
+
+      weighted_mc_prediction(&img->mb_pred[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0, alpha_l0, wp_offset, img->luma_log2_weight_denom, max_imgpel_value);
+    }
+    else
+#endif
+    {
+      mc_prediction(&img->mb_pred[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0); 
+    }
+
+#if 0
+    if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444) ) 
+    {
+      int uv;
+
+      int ioff_cr = (img->mb_cr_size_x == MB_BLOCK_SIZE) ? ioff : ioff >> 1;
+      int joff_cr = (img->mb_cr_size_y == MB_BLOCK_SIZE) ? joff : joff >> 1;
+      int block_size_x_cr = img->mb_cr_size_x == MB_BLOCK_SIZE ? block_size_x : block_size_x >> 1;
+      int block_size_y_cr = img->mb_cr_size_y == MB_BLOCK_SIZE ? block_size_y : block_size_y >> 1;
+
+      vec1_y_cr = vec1_y + ((active_sps->chroma_format_idc == 1)? list[ref_idx]->chroma_vector_adjustment : 0);
+
+      for(uv=0;uv<2;uv++)
+      {
+        get_block_chroma (uv, list[ref_idx], vec1_x, vec1_y_cr, block_size_x_cr, block_size_y_cr, img, tmp_block_l0);
+
+        if (img->apply_weights)
+        {
+          alpha_l0  = img->wp_weight[pred_dir][ref_idx_wp][uv + 1];
+          wp_offset = img->wp_offset[pred_dir][ref_idx_wp][uv + 1];
+
+          weighted_mc_prediction(&img->mb_pred[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0, alpha_l0, wp_offset, img->chroma_log2_weight_denom, img->max_imgpel_value_comp[uv + 1]);
+        }
+        else
+        {
+          mc_prediction(&img->mb_pred[uv + 1][joff_cr], block_size_y_cr, block_size_x_cr, ioff_cr, tmp_block_l0);
+        }
+      }
+    }
+#endif
+  }
+  else
+  {
+#if 0
+    //===== BI-PREDICTION =====
+    short ***l0_mv_array = dec_picture->motion.mv[LIST_0];
+    short ***l1_mv_array = dec_picture->motion.mv[LIST_1];
+
+    short l0_refframe = dec_picture->motion.ref_idx[LIST_0][j4][i4];
+    short l1_refframe = dec_picture->motion.ref_idx[LIST_1][j4][i4];
+    short l0_ref_idx  = l0_refframe;
+    short l1_ref_idx  = l1_refframe;
+
+    check_motion_vector_range(img, l0_mv_array[j4][i4][0], l0_mv_array[j4][i4][1]);
+    check_motion_vector_range(img, l1_mv_array[j4][i4][0], l1_mv_array[j4][i4][1]);
+    vec1_x = i4 * mv_mul + l0_mv_array[j4][i4][0];
+    vec2_x = i4 * mv_mul + l1_mv_array[j4][i4][0];
+
+    vec1_y = (img->block_y_aff + j) * mv_mul + l0_mv_array[j4][i4][1];
+    vec2_y = (img->block_y_aff + j) * mv_mul + l1_mv_array[j4][i4][1];
+
+    get_block_luma(pl, listX[LIST_0 + list_offset][l0_refframe], vec1_x, vec1_y, block_size_x, block_size_y, img, tmp_block_l0);  
+    get_block_luma(pl, listX[LIST_1 + list_offset][l1_refframe], vec2_x, vec2_y, block_size_x, block_size_y, img, tmp_block_l1);  
+
+    if(img->apply_weights)
+    {
+      int wt_list_offset = (active_pps->weighted_bipred_idc==2)? list_offset : 0;
+
+      // This code existed in the original. Seems pointless but copying it here for reference and in case temporal direct breaks.
+      // if (mv_mode==0 && img->direct_spatial_mv_pred_flag==0 ) l1_ref_idx=0;    
+      if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
+        (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
+      {
+        l0_ref_idx >>=1;
+        l1_ref_idx >>=1;
+      }
+
+      alpha_l0  =   img->wbp_weight[LIST_0 + wt_list_offset][l0_ref_idx][l1_ref_idx][0];
+      alpha_l1  =   img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][0];
+      wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][0] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][0] + 1) >>1);
+
+      weighted_bi_prediction(&img->mb_pred[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff, alpha_l0, alpha_l1, wp_offset, (img->luma_log2_weight_denom + 1), max_imgpel_value);
+    }
+    else
+    { 
+      bi_prediction(&img->mb_pred[pl][joff], tmp_block_l0, tmp_block_l1, block_size_y, block_size_x, ioff); 
+    }
+
+    if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444) ) 
+    {
+      int uv;
+
+      int ioff_cr = img->mb_cr_size_x == MB_BLOCK_SIZE ? ioff : ioff >> 1;
+      int joff_cr = img->mb_cr_size_y == MB_BLOCK_SIZE ? joff : joff >> 1;
+      int block_size_x_cr = img->mb_cr_size_x == MB_BLOCK_SIZE ? block_size_x : block_size_x >> 1;
+      int block_size_y_cr = img->mb_cr_size_y == MB_BLOCK_SIZE ? block_size_y : block_size_y >> 1;
+
+      vec1_y_cr = vec1_y + ((active_sps->chroma_format_idc == 1)? listX[LIST_0 + list_offset][l0_refframe]->chroma_vector_adjustment : 0);
+      vec2_y_cr = vec2_y + ((active_sps->chroma_format_idc == 1)? listX[LIST_1 + list_offset][l1_refframe]->chroma_vector_adjustment : 0);
+
+      for(uv=0;uv<2;uv++)
+      {
+        get_block_chroma (uv, listX[LIST_0 + list_offset][l0_refframe], vec1_x, vec1_y_cr, block_size_x_cr, block_size_y_cr, img, tmp_block_l0);
+        get_block_chroma (uv, listX[LIST_1 + list_offset][l1_refframe], vec2_x, vec2_y_cr, block_size_x_cr, block_size_y_cr, img, tmp_block_l1);
+
+        if(img->apply_weights)
+        {
+          int wt_list_offset = (active_pps->weighted_bipred_idc==2)? list_offset : 0;
+
+          alpha_l0  =   img->wbp_weight[LIST_0 + wt_list_offset][l0_ref_idx][l1_ref_idx][uv + 1];
+          alpha_l1  =   img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][uv + 1];
+          wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][uv + 1] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][uv + 1] + 1) >>1);
+
+          weighted_bi_prediction(&img->mb_pred[uv+1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr, alpha_l0, alpha_l1, wp_offset, (img->chroma_log2_weight_denom + 1), img->max_imgpel_value_comp[uv + 1]);
+        }
+        else
+        {
+          bi_prediction(&img->mb_pred[uv + 1][joff_cr], tmp_block_l0, tmp_block_l1, block_size_y_cr, block_size_x_cr, ioff_cr);
+        }
+      }
+    }
+#endif
+  }
+}
+
+void perform_mc_concealment(int decoder, ColorPlane pl, StorablePicture *dec_picture, ImageParameters *img, int pred_dir, int i, int j, int block_size_x, int block_size_y)
+{
+  static int vec1_x=0, vec1_y=0;
+  static const int mv_mul = 16; // 4 * 4
+  
+  int i4   = img->block_x + i;
+  int j4   = img->block_y + j;
+  int ioff = (i << 2);
+  int joff = (j << 2);         
+  
+  assert (pred_dir<=2);
+
+  if (pred_dir != 2)
+  {
+    //===== Single List Prediction =====
+    short       ref_idx = dec_picture->motion.ref_idx[pred_dir][j4][i4];
+    short      ***mv_array = dec_picture->motion.mv[pred_dir];
+    StorablePicture **list = listX[pred_dir];
+
+    vec1_x = i4 * mv_mul + mv_array[j4][i4][0];
+    vec1_y = j4 * mv_mul + mv_array[j4][i4][1];
+
+    get_block_luma (decoder, pl, dec_picture, list[ref_idx], vec1_x, vec1_y, block_size_x, block_size_y, img, tmp_block_l0); 
+    mc_prediction(&img->mb_pred[pl][joff], block_size_y, block_size_x, ioff, tmp_block_l0); 
+  }
+}
diff --git a/lencod/src/explicit_gop.c b/lencod/src/explicit_gop.c
index 92d8b40..bdc443f 100644
--- a/lencod/src/explicit_gop.c
+++ b/lencod/src/explicit_gop.c
@@ -1,4 +1,3 @@
-
 /*!
  *************************************************************************************
  * \file explicit_gop.c
@@ -12,14 +11,16 @@
  *************************************************************************************
  */
 
+#include "contributors.h"
+
 #include <ctype.h>
 #include <limits.h>
 #include "global.h"
-#include "contributors.h"
+
 #include "explicit_gop.h"
 #include "image.h"
 #include "nalucommon.h"
-
+#include "report.h"
 
 /*!
 ************************************************************************
@@ -445,8 +446,14 @@ void encode_enhancement_layer()
   img->b_frame_to_code = 0;
 }
 
+/*!
+************************************************************************
+* \brief
+*    POC-based reference management (FRAME)
+************************************************************************
+*/
 
-void poc_based_ref_management(int current_pic_num)
+void poc_based_ref_management_frame_pic(int current_pic_num)
 {
   unsigned i, pic_num = 0;
 
@@ -456,7 +463,7 @@ void poc_based_ref_management(int current_pic_num)
   if (img->dec_ref_pic_marking_buffer!=NULL)
     return;
 
-  if ((dpb.ref_frames_in_buffer+dpb.ltref_frames_in_buffer)==0)
+  if ((dpb.ref_frames_in_buffer + dpb.ltref_frames_in_buffer)==0)
     return;
 
   for (i=0; i<dpb.used_size;i++)
@@ -481,3 +488,60 @@ void poc_based_ref_management(int current_pic_num)
   img->dec_ref_pic_marking_buffer = tmp_drpm2;
 
 }
+
+/*!
+************************************************************************
+* \brief
+*    POC-based reference management (FIELD)
+************************************************************************
+*/
+
+void poc_based_ref_management_field_pic(int current_pic_num)
+{
+  unsigned int i, pic_num1 = 0, pic_num2 = 0;
+
+  int min_poc=INT_MAX;
+  DecRefPicMarking_t *tmp_drpm,*tmp_drpm2, *tmp_drpm3;
+
+  if (img->dec_ref_pic_marking_buffer!=NULL)
+    return;
+
+  if ((dpb.ref_frames_in_buffer+dpb.ltref_frames_in_buffer)==0)
+    return;
+
+  if ( img->structure == TOP_FIELD )
+  {
+    for (i=0; i<dpb.used_size;i++)
+    {
+      if (dpb.fs[i]->is_reference && (!(dpb.fs[i]->is_long_term)) && dpb.fs[i]->poc < min_poc)
+      {      
+        min_poc  = dpb.fs[i]->poc;
+        pic_num1 = dpb.fs[i]->top_field->pic_num;
+        pic_num2 = dpb.fs[i]->bottom_field->pic_num;
+      }
+    }
+  }
+
+  if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm");
+  tmp_drpm->Next=NULL;
+  tmp_drpm->memory_management_control_operation = 0;
+
+  if ( img->structure == BOTTOM_FIELD )
+  {
+    img->dec_ref_pic_marking_buffer = tmp_drpm;
+    return;
+  }
+
+  if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm2");
+  tmp_drpm2->Next=tmp_drpm;
+  tmp_drpm2->memory_management_control_operation = 1;
+  tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num1 - 1;
+
+  if (NULL==(tmp_drpm3=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm3");
+  tmp_drpm3->Next=tmp_drpm2;
+  tmp_drpm3->memory_management_control_operation = 1;
+  tmp_drpm3->difference_of_pic_nums_minus1 = current_pic_num - pic_num2 - 1;
+
+  img->dec_ref_pic_marking_buffer = tmp_drpm3;
+}
+
diff --git a/lencod/src/filehandle.c b/lencod/src/filehandle.c
index a58ee6e..56079d3 100644
--- a/lencod/src/filehandle.c
+++ b/lencod/src/filehandle.c
@@ -15,6 +15,7 @@
 #include "contributors.h"
 
 #include "global.h"
+#include "enc_statistics.h"
 
 #include "rtp.h"
 #include "annexb.h"
diff --git a/lencod/src/header.c b/lencod/src/header.c
index ebf8c83..1c29343 100644
--- a/lencod/src/header.c
+++ b/lencod/src/header.c
@@ -41,7 +41,7 @@ int assignSE2partition_DP[SE_MAX_ELEMENTS] =
 static int ref_pic_list_reordering(Bitstream *bitstream);
 static int dec_ref_pic_marking    (Bitstream *bitstream);
 static int pred_weight_table      (Bitstream *bitstream);
-
+static int get_picture_type(void);
 /*!
  ********************************************************************************************
  * \brief
@@ -67,7 +67,7 @@ int SliceHeader(void)
   else
     len  = ue_v("SH: first_mb_in_slice", img->current_mb_nr,   bitstream);
 
-  len += ue_v("SH: slice_type",        get_picture_type (),   bitstream);
+  len += ue_v("SH: slice_type", get_picture_type (),   bitstream);
 
   len += ue_v("SH: pic_parameter_set_id" , active_pps->pic_parameter_set_id ,bitstream);
 
@@ -198,14 +198,13 @@ int SliceHeader(void)
     if (img->DFDisableIdc!=1)
     {
       len += se_v ("SH: slice_alpha_c0_offset_div2", img->DFAlphaC0Offset / 2, bitstream);
-
-      len += se_v ("SH: slice_beta_offset_div2", img->DFBetaOffset / 2, bitstream);
+      len += se_v ("SH: slice_beta_offset_div2    ", img->DFBetaOffset / 2, bitstream);
     }
   }
 
 
-  if ( active_pps->num_slice_groups_minus1>0 &&
-    active_pps->slice_group_map_type>=3 && active_pps->slice_group_map_type<=5)
+  if ( active_pps->num_slice_groups_minus1 > 0 &&
+    active_pps->slice_group_map_type >= 3 && active_pps->slice_group_map_type <= 5)
   {
     numtmp=img->PicHeightInMapUnits*img->PicWidthInMbs/(float)(active_pps->slice_group_change_rate_minus1+1)+1;
     num_bits_slice_group_change_cycle = (int)ceil(log(numtmp)/log(2));
@@ -477,7 +476,7 @@ static int pred_weight_table(Bitstream *bitstream)
  *    symbol value for picture type
  ************************************************************************
  */
-int get_picture_type()
+static int get_picture_type()
 {
   // set this value to zero for transmission without signaling
   // that the whole picture has the same slice type
diff --git a/lencod/src/image.c b/lencod/src/image.c
index 34ca638..a9e130d 100644
--- a/lencod/src/image.c
+++ b/lencod/src/image.c
@@ -32,10 +32,11 @@
 
 #include "global.h"
 
-#include "refbuf.h"
+#include "filehandle.h"
 #include "mbuffer.h"
 #include "img_luma.h"
 #include "img_chroma.h"
+#include "img_distortion.h"
 #include "intrarefresh.h"
 #include "fmo.h"
 #include "sei.h"
@@ -43,50 +44,41 @@
 #include "nalu.h"
 #include "ratectl.h"
 #include "mb_access.h"
-#include "output.h"
 #include "cabac.h"
 #include "context_ini.h"
+#include "enc_statistics.h"
 #include "conformance.h"
 
 #include "q_matrix.h"
 #include "q_offsets.h"
 #include "quant4x4.h"
 #include "quant8x8.h"
+#include "quantChroma.h"
 #include "wp.h"
 #include "input.h"
+#include "image.h"
+#include "errdo.h"
+
 
 extern pic_parameter_set_rbsp_t *PicParSet[MAXPPS];
 
-void code_a_picture(Picture *pic);
-void frame_picture (Picture *frame, int rd_pass);
-void field_picture(Picture *top, Picture *bottom);
-void prepare_enc_frame_picture (StorablePicture **stored_pic);
+extern void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***);
 
+static void code_a_picture(Picture *pic);
+static void field_picture(Picture *top, Picture *bottom);
+static void prepare_enc_frame_picture (StorablePicture **stored_pic);
 static int  writeout_picture(Picture *pic);
-
 static int  picture_structure_decision(Picture *frame, Picture *top, Picture *bot);
-static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v);
-
-static void find_snr(void);
-static void find_distortion(void);
-
- 
-
-static void field_mode_buffer(int bit_field, float snr_field_y, float snr_field_u, float snr_field_v);
-static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v);
-
-static void init_frame(void);
-static void init_field(void);
-
-static void put_buffer_frame(void);
-static void put_buffer_top(void);
-static void put_buffer_bot(void);
-
-static void copy_motion_vectors_MB(void);
-
+static void distortion_fld (Picture *field_pic);
+static void field_mode_buffer (ImageParameters *img, InputParameters *params);
+static void frame_mode_buffer (ImageParameters *img, InputParameters *params);
+static void init_frame(ImageParameters *img);
+static void init_field(ImageParameters *img);
+static void put_buffer_frame(ImageParameters *img);
+static void put_buffer_top(ImageParameters *img);
+static void put_buffer_bot(ImageParameters *img);
 static void PaddAutoCropBorders (FrameFormat output, int img_size_x, int img_size_y, int img_size_x_cr, int img_size_y_cr);
-
-static void writeUnit(Bitstream* currStream ,int partition);
+static void writeUnit(Bitstream* currStream, int partition);
 static void rdPictureCoding(void);
 
 #ifdef _ADAPT_LAST_GROUP_
@@ -120,7 +112,7 @@ void MbAffPostProc(void)
   {
     for (i=0; i<(int)img->PicSizeInMbs; i+=2)
     {
-      if (enc_picture->mb_field[i])
+      if (enc_picture->motion.mb_field[i])
       {
         get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
         for (y=0; y<(2*MB_BLOCK_SIZE);y++)
@@ -153,7 +145,7 @@ void MbAffPostProc(void)
   {
     for (i=0; i<(int)img->PicSizeInMbs; i+=2)
     {
-      if (enc_picture->mb_field[i])
+      if (enc_picture->motion.mb_field[i])
       {
         get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
         for (y=0; y<(2*MB_BLOCK_SIZE);y++)
@@ -178,11 +170,53 @@ void MbAffPostProc(void)
  */
 void set_slice_type(int slice_type)
 {
-    img->type = slice_type;            // set slice type
-    img->RCMinQP = params->RCMinQP[img->type];
-    img->RCMaxQP = params->RCMaxQP[img->type];
+  img->type = slice_type;            // set slice type
+  img->RCMinQP = params->RCMinQP[img->type];
+  img->RCMaxQP = params->RCMaxQP[img->type];
 }
 
+void code_a_plane(ImageParameters *img, Picture *pic)
+{
+  unsigned int NumberOfCodedMBs = 0;
+  int SliceGroup = 0;
+  // The slice_group_change_cycle can be changed here.
+  // FmoInit() is called before coding each picture, frame or field
+  img->slice_group_change_cycle=1;
+  FmoInit(img, active_pps, active_sps);
+  FmoStartPicture ();           //! picture level initialization of FMO
+
+  CalculateQuantParam();
+  CalculateOffsetParam();
+
+  if(params->Transform8x8Mode)
+  {
+    CalculateQuant8Param();
+    CalculateOffset8Param();
+  }
+
+  reset_pic_bin_count();
+  img->bytes_in_picture = 0;
+
+  while (NumberOfCodedMBs < img->PicSizeInMbs)       // loop over slices
+  {
+    // Encode one SLice Group
+    while (!FmoSliceGroupCompletelyCoded (SliceGroup))
+    {
+      // Encode the current slice
+      NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
+      FmoSetLastMacroblockInSlice (img->current_mb_nr);
+      // Proceed to next slice
+      img->current_slice_nr++;
+      stats->bit_slice = 0;
+    }
+    // Proceed to next SliceGroup
+    SliceGroup++;
+  }
+  FmoEndPicture ();
+
+  if ((params->SkipDeBlockNonRef == 0) || (img->nal_reference_idc != 0))
+    DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable deblocking filter 
+}
 /*!
  ************************************************************************
  * \brief
@@ -194,13 +228,8 @@ void set_slice_type(int slice_type)
  *    coding
  ************************************************************************
  */
-void code_a_picture(Picture *pic)
+static void code_a_picture(Picture *pic)
 {
-  unsigned int NumberOfCodedMBs = 0;
-  int SliceGroup = 0;
-  int j;
-
-  int nplane;
   int pl;
   int idr_refresh;
 
@@ -218,122 +247,39 @@ void code_a_picture(Picture *pic)
     || (idr_refresh && (img->type == I_SLICE || img->type==SI_SLICE)&& (!(img->structure==BOTTOM_FIELD)));
 
   pic->no_slices = 0;
-  pic->distortion_u = pic->distortion_v = pic->distortion_y = 0.0;
 
   RandomIntraNewPicture ();     //! Allocates forced INTRA MBs (even for fields!)
 
   if( IS_INDEPENDENT( params ) )
   {
-    for( pl=0; pl<MAX_PLANE; pl++ ){
+    for( pl=0; pl<MAX_PLANE; pl++ )
+    {
       img->current_mb_nr = 0;
       img->current_slice_nr = 0;
       img->SumFrameQP = 0;
-      SliceGroup = 0;
-      NumberOfCodedMBs = 0;
       img->colour_plane_id = pl;
-
-      // The slice_group_change_cycle can be changed here.
-      // FmoInit() is called before coding each picture, frame or field
-      img->slice_group_change_cycle=1;
-      FmoInit(img, active_pps, active_sps);
-      FmoStartPicture ();           //! picture level initialization of FMO
-
-      CalculateQuantParam();
-      CalculateOffsetParam();
-
-      if(params->Transform8x8Mode)
-      {
-        CalculateQuant8Param();
-        CalculateOffset8Param();
-      }
-
-      reset_pic_bin_count();
-      img->bytes_in_picture = 0;
-
-      while (NumberOfCodedMBs < img->PicSizeInMbs)       // loop over slices
-      {
-        // Encode one SLice Group
-        while (!FmoSliceGroupCompletelyCoded (SliceGroup))
-        {
-          // Encode the current slice
-          NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
-          FmoSetLastMacroblockInSlice (img->current_mb_nr);
-          // Proceed to next slice
-          img->current_slice_nr++;
-          stats->bit_slice = 0;
-        }
-        // Proceed to next SliceGroup
-        SliceGroup++;
-      }
-      FmoEndPicture ();
-    }
-  } 
-  else
-  {
-    // The slice_group_change_cycle can be changed here.
-    // FmoInit() is called before coding each picture, frame or field
-    img->slice_group_change_cycle=1;
-    FmoInit(img, active_pps, active_sps);
-    FmoStartPicture ();           //! picture level initialization of FMO
-
-    CalculateQuantParam();
-    CalculateOffsetParam();
-
-    if(params->Transform8x8Mode)
-    {
-      CalculateQuant8Param();
-      CalculateOffset8Param();
-    }
-
-    reset_pic_bin_count();
-    img->bytes_in_picture = 0;
-
-    while (NumberOfCodedMBs < img->PicSizeInMbs)       // loop over slices
-    {
-      // Encode one SLice Group
-      while (!FmoSliceGroupCompletelyCoded (SliceGroup))
-      {
-        // Encode the current slice
-        NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
-        FmoSetLastMacroblockInSlice (img->current_mb_nr);
-        // Proceed to next slice
-        img->current_slice_nr++;
-        stats->bit_slice = 0;
-      }
-      // Proceed to next SliceGroup
-      SliceGroup++;
+      
+      code_a_plane(img, pic);
     }
-    FmoEndPicture ();
   }
-
-  if( IS_INDEPENDENT(params) )
-  {
-    for( nplane=0; nplane<MAX_PLANE; nplane++ )
-    {
-      change_plane_JV( nplane );
-      // Modified for Fast Mode Decision. Inchoon Choi, SungKyunKwan Univ.
-      if (params->rdopt == 3 && (img->nal_reference_idc != 0))
-        for (j = 0; j < params->NoOfDecoders; j++)
-          DeblockFrame (img, decs->decY_best[j], NULL);
-
-      DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable deblocking filter 
-    }
-  } 
   else
   {
-    // Modified for Fast Mode Decision. Inchoon Choi, SungKyunKwan Univ.
-    if ((params->rdopt == 3) && (img->nal_reference_idc != 0))
-      for (j = 0; j < params->NoOfDecoders; j++)
-        DeblockFrame (img, decs->decY_best[j], NULL);
-
-    DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable deblocking filter
+    code_a_plane(img, pic);
   }
 
   if (img->MbaffFrameFlag)
     MbAffPostProc();
 }
 
-
+void free_pictures(int stored_pic)
+{
+  int i;
+  for (i = 0; i < 6; i++)
+  {
+    if (i != stored_pic)
+      free_storable_picture(enc_frame_picture[i]);        
+  }
+}
 
 /*!
  ************************************************************************
@@ -350,7 +296,6 @@ int encode_one_frame (void)
 
   //Rate control
   int bits = 0;
-  int bits_frm = 0, bits_fld = 0;
 
 #ifdef _LEAKYBUCKET_
   //extern long Bit_Buffer[20000];
@@ -360,9 +305,6 @@ int encode_one_frame (void)
   time_t ltime1, ltime2, tmp_time;
   struct TIMEB tstruct1, tstruct2;
 
-  float dis_frm = 0.0, dis_frm_y = 0.0, dis_frm_u = 0.0, dis_frm_v = 0.0;
-  float dis_fld = 0.0, dis_fld_y = 0.0, dis_fld_u = 0.0, dis_fld_v = 0.0;
-
   me_time=0;
   img->rd_pass = 0;
 
@@ -393,21 +335,18 @@ int encode_one_frame (void)
   UpdateRandomAccess ();
 */
 
-
   if ((params->ResendPPS) && (img->frm_number !=0))
   {
-    stats->bit_ctr_parametersets_n=write_PPS(0, 0);
-    stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
+    stats->bit_ctr_parametersets_n = write_PPS(0, 0);
+    stats->bit_ctr_parametersets  += stats->bit_ctr_parametersets_n;
   }
 
-  put_buffer_frame ();      // sets the pointers to the frame structures
+  put_buffer_frame (img);      // sets the pointers to the frame structures
                             // (and not to one of the field structures)
-  init_frame ();
-  //FrameNumberInFile = CalculateFrameNumber();
+  init_frame (img);
 
   ReadOneFrame (FrameNumberInFile, params->infile_header, &params->source, &params->output);
-
-  PaddAutoCropBorders (params->output, img->width, img->height,img->width_cr, img->height_cr);
+  PaddAutoCropBorders (params->output, img->width, img->height, img->width_cr, img->height_cr);
 
   // set parameters for direct mode and deblocking filter
   img->direct_spatial_mv_pred_flag = params->direct_spatial_mv_pred_flag;
@@ -419,13 +358,14 @@ int encode_one_frame (void)
   img->AdaptiveRounding            = params->AdaptiveRounding; 
   // Initialize quantization functions based on rounding/quantization method
   // Done here since we may wish to disable adaptive rounding on occasional intervals (even at a frame or gop level).
-  init_quant_4x4(img);
-  init_quant_8x8(img);
+  init_quant_4x4(params, img);
+  init_quant_8x8(params, img);
+  init_quant_Chroma(params, img);
 
   // Following code should consider optimal coding mode. Currently also does not support
   // multiple slices per frame.
-  frame_ctr[img->type]++;
-  snr->frame_ctr++;
+
+  dist->frame_ctr++;
 
   if(img->type == SP_SLICE)
   {
@@ -439,12 +379,19 @@ int encode_one_frame (void)
   {
     sp2_frame_indicator=0;
   }
+  if ( params->WPMCPrecision )
+  {
+    wpxInitWPXPasses(params);
+    pWPX->curr_wp_rd_pass = pWPX->wp_rd_passes;
+    pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
+  }
+
 
   if (params->PicInterlace == FIELD_CODING)
   {
     //Rate control
     if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
-      generic_RC->FieldControl=1;
+      generic_RC->FieldControl = 1;
 
     img->field_picture = 1;  // we encode fields
     field_picture (field_pic[0], field_pic[1]);
@@ -455,7 +402,7 @@ int encode_one_frame (void)
     int tmpFrameQP;
     //Rate control
     if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
-      generic_RC->FieldControl=0;
+      generic_RC->FieldControl = 0;
 
     // For frame coding, turn MB level field/frame coding flag on
     if (params->MbInterlace)
@@ -465,7 +412,7 @@ int encode_one_frame (void)
 
     //Rate control
     if(params->RCEnable)
-      rc_init_frame(FrameNumberInFile);   
+      rc_init_frame(FrameNumberInFile);
 
     if (params->GenerateMultiplePPS)
       active_pps = PicParSet[0];
@@ -476,6 +423,7 @@ int encode_one_frame (void)
     {
       rdPictureCoding();
     }
+
     tmpFrameQP = img->SumFrameQP; // call it here since rdPictureCoding buffers it and may modify it
 
     if ((img->type==SP_SLICE) && (si_frame_indicator==0) && (params->si_frame_indicator))
@@ -489,6 +437,7 @@ int encode_one_frame (void)
       // output the transformed and quantized coefficients (useful for switching SP frames)
       output_SP_coefficients();
     }
+    
     // For field coding, turn MB level field/frame coding flag off
     if (params->MbInterlace)
       mb_adaptive = 0;
@@ -504,11 +453,6 @@ int encode_one_frame (void)
       img->field_picture = 1;  // we encode fields
       field_picture (field_pic[0], field_pic[1]);
 
-      //! Note: the distortion for a field coded picture is stored in the top field
-      //! the distortion values in the bottom field are dummies
-      dis_fld = field_pic[0]->distortion_y + field_pic[0]->distortion_u + field_pic[0]->distortion_v;
-      dis_frm = frame_pic[0]->distortion_y + frame_pic[0]->distortion_u + frame_pic[0]->distortion_v;
-
       if(img->rd_pass == 0)
         img->fld_flag = picture_structure_decision (frame_pic[0], field_pic[0], field_pic[1]);
       else if(img->rd_pass == 1)
@@ -527,31 +471,30 @@ int encode_one_frame (void)
     }
     else
       img->fld_flag = 0;
+    
     img->SumFrameQP = tmpFrameQP;
   }
 
+  stats->frame_counter++;
+  stats->frame_ctr[img->type]++;
+
   if (img->fld_flag)
     stats->bit_ctr_emulationprevention += stats->em_prev_bits_fld;
   else
     stats->bit_ctr_emulationprevention += stats->em_prev_bits_frm;
 
-  if (img->type != B_SLICE)
-  {
-    img->pstruct_next_P = img->fld_flag;
-  }
-
   // Here, img->structure may be either FRAME or BOTTOM FIELD depending on whether AFF coding is used
   // The picture structure decision changes really only the fld_flag
 
   if (img->fld_flag)            // field mode (use field when fld_flag=1 only)
   {
-    field_mode_buffer (bits_fld, dis_fld_y, dis_fld_u, dis_fld_v);
+    field_mode_buffer (img, params);
     writeout_picture (field_pic[0]);
     writeout_picture (field_pic[1]);
   }
   else                          //frame mode
   {
-    frame_mode_buffer (bits_frm, dis_frm_y, dis_frm_u, dis_frm_v);
+    frame_mode_buffer (img, params);
   
     if (img->type==SP_SLICE && si_frame_indicator == 1)
     {
@@ -601,71 +544,54 @@ int encode_one_frame (void)
   if (params->PicInterlace == FRAME_CODING)
   {
     if ((params->rdopt == 3) && (img->nal_reference_idc != 0))
-      UpdateDecoders ();      // simulate packet losses and move decoded image to reference buffers
+    {
+      UpdateDecoders (params, img, enc_picture);      // simulate packet losses and move decoded image to reference buffers
+    }
 
     if (params->RestrictRef)
       UpdatePixelMap ();
   }
 
-  if (params->Verbose != 0)
-  {
-    find_snr ();
-  }
-  else
-  {
-    snr->snr_y = 0.0;
-    snr->snr_u = 0.0;
-    snr->snr_v = 0.0;
-    snr->sse_y = 0.0;
-    snr->sse_u = 0.0;
-    snr->sse_v = 0.0;
-  }
+  compute_distortion();
 
   // redundant pictures: save reconstruction to calculate SNR and replace reference picture
-  if(params->redundant_pic_flag && key_frame)
+
+  if(params->redundant_pic_flag)
   {
-    for(i=0; i<img->width; i++)
+    int k;
+    if(key_frame)
     {
       for(j=0; j<img->height; j++)
       {
-        imgY_tmp[j][i] = enc_frame_picture[0]->imgY[j][i];
+        memcpy(imgY_tmp[j], enc_frame_picture[0]->imgY[j], img->width * sizeof(imgpel));
       }
-    }
-    for(i=0; i<img->width_cr; i++)
-    {
-      for(j=0; j<img->height_cr; j++)
+
+      for (k = 0; k < 2; k++)
       {
-        imgUV_tmp[0][j][i] = enc_frame_picture[0]->imgUV[0][j][i];
-        imgUV_tmp[1][j][i] = enc_frame_picture[0]->imgUV[1][j][i];
+        for(j=0; j<img->height_cr; j++)
+        {
+          memcpy(imgUV_tmp[k][j], enc_frame_picture[0]->imgUV[k][j], img->width_cr * sizeof(imgpel));
+        }
       }
     }
-  }
 
-  if(params->redundant_pic_flag && redundant_coding)
-  {
-    for(i=0; i<img->width; i++)
+    if(redundant_coding)
     {
       for(j=0; j<img->height; j++)
       {
-        enc_frame_picture[0]->imgY[j][i] = imgY_tmp[j][i];
+        memcpy(enc_frame_picture[0]->imgY[j], imgY_tmp[j], img->width * sizeof(imgpel));
       }
-    }
-    for(i=0; i<img->width_cr; i++)
-    {
-      for(j=0; j<img->height_cr; j++)
+      for (k = 0; k < 2; k++)
       {
-        enc_frame_picture[0]->imgUV[0][j][i] = imgUV_tmp[0][j][i];
-        enc_frame_picture[0]->imgUV[1][j][i] = imgUV_tmp[1][j][i];
+        for(j=0; j<img->height_cr; j++)
+        {
+          memcpy(enc_frame_picture[0]->imgUV[k][j], imgUV_tmp[k][j], img->width_cr * sizeof(imgpel));
+        }
       }
     }
   }
 
-  time (&ltime2);               // end time sec
-  ftime (&tstruct2);            // end time ms
-
-  tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm);
-  tot_time = tot_time + tmp_time;
-
+ 
   if (params->PicInterlace == ADAPTIVE_CODING)
   {
     if (img->fld_flag)
@@ -673,52 +599,48 @@ int encode_one_frame (void)
       // store bottom field
       store_picture_in_dpb(enc_field_picture[1]);
       free_storable_picture(enc_frame_picture[0]);
+      free_storable_picture(enc_frame_picture[1]);
+      free_storable_picture(enc_frame_picture[2]);
     }
     else
     {
       // replace top with frame
-      replace_top_pic_with_frame(enc_frame_picture[0]);
-      free_storable_picture(enc_field_picture[1]);
-    }
-  }
-  else
-  {
-    if (img->fld_flag)
-    {
-      store_picture_in_dpb(enc_field_picture[1]);
-    }
-    else
-    {
       if (img->rd_pass==2)
       {
-        store_picture_in_dpb(enc_frame_picture[2]);
+        replace_top_pic_with_frame(enc_frame_picture[2]);
         free_storable_picture(enc_frame_picture[0]);
         free_storable_picture(enc_frame_picture[1]);
       }
       else if (img->rd_pass==1)
       {
-        store_picture_in_dpb(enc_frame_picture[1]);
+        replace_top_pic_with_frame(enc_frame_picture[1]);
         free_storable_picture(enc_frame_picture[0]);
         free_storable_picture(enc_frame_picture[2]);
       }
       else
       {
-        if(params->redundant_pic_flag==0)
+        if(params->redundant_pic_flag==0 || (key_frame==0))
         {
-          store_picture_in_dpb(enc_frame_picture[0]);
+          replace_top_pic_with_frame(enc_frame_picture[0]);
           free_storable_picture(enc_frame_picture[1]);
           free_storable_picture(enc_frame_picture[2]);
         }
-        else
-        {
-          // key picture will be stored in dpb after redundant picture is coded
-          if(key_frame==0)
-          {
-            store_picture_in_dpb(enc_frame_picture[0]);
-            free_storable_picture(enc_frame_picture[1]);
-            free_storable_picture(enc_frame_picture[2]);
-          }
-        }
+      }
+      free_storable_picture(enc_field_picture[1]);
+    }
+  }
+  else
+  {
+    if (img->fld_flag)
+    {
+      store_picture_in_dpb(enc_field_picture[1]);
+    }
+    else
+    {
+      if ((params->redundant_pic_flag != 1) || (key_frame == 0))
+      {
+        store_picture_in_dpb (enc_frame_picture[img->rd_pass]);
+        free_pictures(img->rd_pass);
       }
     }
   }
@@ -746,6 +668,12 @@ int encode_one_frame (void)
     prev_frame_no = frame_no;
   }
 
+  time (&ltime2);               // end time sec
+  ftime (&tstruct2);            // end time ms
+
+  tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm);
+  tot_time = tot_time + tmp_time;
+
   if (stats->bit_ctr_parametersets_n!=0)
     ReportNALNonVLCBits(tmp_time, me_time);
 
@@ -768,19 +696,19 @@ int encode_one_frame (void)
     switch (img->type)
     {
     case I_SLICE:
-      stats->bit_ctr_I += stats->bit_ctr - stats->bit_ctr_n;
+      stats->bit_counter[I_SLICE] += stats->bit_ctr - stats->bit_ctr_n;
       ReportIntra(tmp_time,me_time);
       break;
     case SP_SLICE:
-      stats->bit_ctr_P += stats->bit_ctr - stats->bit_ctr_n;
+      stats->bit_counter[P_SLICE] += stats->bit_ctr - stats->bit_ctr_n;
       ReportSP(tmp_time,me_time);
       break;
     case B_SLICE:
-      stats->bit_ctr_B += stats->bit_ctr - stats->bit_ctr_n;
+      stats->bit_counter[B_SLICE] += stats->bit_ctr - stats->bit_ctr_n;
       ReportB(tmp_time,me_time);
       break;
     default:      // P
-      stats->bit_ctr_P += stats->bit_ctr - stats->bit_ctr_n;
+      stats->bit_counter[P_SLICE] += stats->bit_ctr - stats->bit_ctr_n;
       ReportP(tmp_time,me_time);
     }
   }
@@ -800,7 +728,7 @@ int encode_one_frame (void)
     rc_update_picture_ptr( bits );
   stats->bit_ctr_n = stats->bit_ctr;
 
-  stats->bit_ctr_parametersets_n=0;
+  stats->bit_ctr_parametersets_n = 0;
 
   if ( img->type == I_SLICE && img->nal_reference_idc)
   {
@@ -886,7 +814,7 @@ void copy_params(void)
  *    Prepare and allocate an encoded frame picture structure
  ************************************************************************
  */
-void prepare_enc_frame_picture (StorablePicture **stored_pic)
+static void prepare_enc_frame_picture (StorablePicture **stored_pic)
 {
   (*stored_pic)              = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
   
@@ -907,6 +835,21 @@ void prepare_enc_frame_picture (StorablePicture **stored_pic)
   copy_params();
 }
 
+static void calc_picture_bits(Picture *frame)
+{
+  int i, j;
+  Slice *thisSlice = NULL;
+
+  frame->bits_per_picture = 0;
+
+  for ( i = 0; i < frame->no_slices; i++ )
+  {
+    thisSlice = frame->slices[i];
+
+    for ( j = 0; j < thisSlice->max_part_nr; j++ )
+      frame->bits_per_picture += 8 * ((thisSlice->partArr[j]).bitstream)->byte_pos;
+  }
+}
 /*!
  ************************************************************************
  * \brief
@@ -922,39 +865,18 @@ void frame_picture (Picture *frame, int rd_pass)
   //set mv limits to frame type
   update_mv_limits(img, 0);
 
-  if ( rd_pass == 2 )
-    prepare_enc_frame_picture( &enc_frame_picture[2] );
-  else if ( rd_pass == 1 )
-    prepare_enc_frame_picture( &enc_frame_picture[1] );
-  else
+  if( IS_INDEPENDENT(params) )
   {
-    if( IS_INDEPENDENT(params) )
+    for( nplane=0; nplane<MAX_PLANE; nplane++ )
     {
-      for( nplane=0; nplane<MAX_PLANE; nplane++ )
-      {
-        enc_frame_picture_JV[nplane]  = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
-        img->ThisPOC=enc_frame_picture_JV[nplane]->poc=img->framepoc;
-        enc_frame_picture_JV[nplane]->top_poc    = img->toppoc;
-        enc_frame_picture_JV[nplane]->bottom_poc = img->bottompoc;
-        enc_frame_picture_JV[nplane]->frame_poc = img->framepoc;
-
-        enc_frame_picture_JV[nplane]->pic_num = img->frame_num;
-        enc_frame_picture_JV[nplane]->frame_num = img->frame_num;
-        enc_frame_picture_JV[nplane]->coded_frame = 1;
-
-        enc_frame_picture_JV[nplane]->MbaffFrameFlag = img->MbaffFrameFlag = (params->MbInterlace != FRAME_CODING);
-        get_mb_block_pos = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal;
-        getNeighbour = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour;
-
-        enc_picture=enc_frame_picture_JV[nplane];
-        copy_params();
-      }
+      prepare_enc_frame_picture( &enc_frame_picture_JV[nplane] );      
     }
-    else
-    {
-      prepare_enc_frame_picture( &enc_frame_picture[0] );
-     }
   }
+  else
+  {
+    prepare_enc_frame_picture( &enc_frame_picture[rd_pass] );
+  }
+
 
   stats->em_prev_bits_frm = 0;
   stats->em_prev_bits = &stats->em_prev_bits_frm;
@@ -967,14 +889,12 @@ void frame_picture (Picture *frame, int rd_pass)
     make_frame_picture_JV();
   }
 
-  frame->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos);
+  calc_picture_bits(frame);
 
   if (img->structure==FRAME)
   {
     find_distortion ();
-    frame->distortion_y = snr->snr_y;
-    frame->distortion_u = snr->snr_u;
-    frame->distortion_v = snr->snr_v;
+    frame->distortion = dist->metric[SSE];
   }
 }
 
@@ -985,7 +905,7 @@ void frame_picture (Picture *frame, int rd_pass)
  *    Encodes a field picture, consisting of top and bottom field
  ************************************************************************
  */
-void field_picture (Picture *top, Picture *bottom)
+static void field_picture (Picture *top, Picture *bottom)
 {
   //Rate control
   int old_pic_type;              // picture type of top field used for rate control
@@ -1022,8 +942,8 @@ void field_picture (Picture *top, Picture *bottom)
   enc_picture = enc_field_picture[0];
   copy_params();
 
-  put_buffer_top ();
-  init_field ();
+  put_buffer_top (img);
+  init_field (img);
   if (img->type == B_SLICE)       //all I- and P-frames
     nextP_tr_fld--;
 
@@ -1039,7 +959,7 @@ void field_picture (Picture *top, Picture *bottom)
 
   store_picture_in_dpb(enc_field_picture[0]);
 
-  top->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos);
+  calc_picture_bits(top);
 
   //Rate control
   TopFieldBits=top->bits_per_picture;
@@ -1059,10 +979,10 @@ void field_picture (Picture *top, Picture *bottom)
   img->structure = BOTTOM_FIELD;
   enc_picture = enc_field_picture[1];
   copy_params();
-  put_buffer_bot ();
+  put_buffer_bot (img);
   img->number++;
 
-  init_field ();
+  init_field (img);
 
   if (img->type == B_SLICE)       //all I- and P-frames
     nextP_tr_fld++;             //check once coding B field
@@ -1079,12 +999,11 @@ void field_picture (Picture *top, Picture *bottom)
   enc_picture->structure = (PictureStructure) 2;
   code_a_picture(field_pic[1]);
 
-  bottom->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos);
+  calc_picture_bits(bottom);
 
   // the distortion for a field coded frame (consisting of top and bottom field)
   // lives in the top->distortion variables, the bottom-> are dummies
-  distortion_fld (&top->distortion_y, &top->distortion_u, &top->distortion_v);
-
+  distortion_fld (top);
 }
 
 
@@ -1094,7 +1013,7 @@ void field_picture (Picture *top, Picture *bottom)
  *    Distortion Field
  ************************************************************************
  */
-static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v)
+static void distortion_fld (Picture *field_pic)
 {
 
   img->number /= 2;
@@ -1104,21 +1023,17 @@ static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v
 
   combine_field ();
 
-  pCurImg   = imgY_org_frm;
-  imgUV_org = imgUV_org_frm;
+  pCurImg   = img_org_frm[0];
+  pImgOrg[0] = img_org_frm[0];
 
-  pImgOrg[0] = imgY_org_frm;
   if (params->yuv_format != YUV400)
   {
-    pImgOrg[1] = imgUV_org_frm[0];
-    pImgOrg[2] = imgUV_org_frm[1];
+    pImgOrg[1] = img_org_frm[1];
+    pImgOrg[2] = img_org_frm[2];
   }
 
   find_distortion ();   // find snr from original frame picture
-
-  *dis_fld_y = snr->snr_y;
-  *dis_fld_u = snr->snr_u;
-  *dis_fld_v = snr->snr_v;
+  field_pic->distortion = dist->metric[SSE];
 }
 
 
@@ -1132,17 +1047,18 @@ static int picture_structure_decision (Picture *frame, Picture *top, Picture *bo
 {
   double lambda_picture;
   int bframe = (img->type == B_SLICE);
-  float snr_frame, snr_field;
+  float sse_frame, sse_field;
   int bit_frame, bit_field;
 
   lambda_picture = 0.68 * pow (2, img->bitdepth_lambda_scale + ((img->qp - SHIFT_QP) / 3.0)) * (bframe ? 1 : 1);
 
-  snr_frame = frame->distortion_y + frame->distortion_u + frame->distortion_v;
+  sse_frame = frame->distortion.value[0] + frame->distortion.value[1] + frame->distortion.value[2];
   //! all distrortions of a field picture are accumulated in the top field
-  snr_field = top->distortion_y + top->distortion_u + top->distortion_v;
+  sse_field = top->distortion.value[0] + top->distortion.value[1] + top->distortion.value[2];
+
   bit_field = top->bits_per_picture + bot->bits_per_picture;
   bit_frame = frame->bits_per_picture;
-  return decide_fld_frame (snr_frame, snr_field, bit_field, bit_frame, lambda_picture);
+  return decide_fld_frame (sse_frame, sse_field, bit_field, bit_frame, lambda_picture);
 }
 
 
@@ -1152,13 +1068,9 @@ static int picture_structure_decision (Picture *frame, Picture *top, Picture *bo
  *    Field Mode Buffer
  ************************************************************************
  */
-static void field_mode_buffer (int bit_field, float snr_field_y, float snr_field_u, float snr_field_v)
+static void field_mode_buffer (ImageParameters *img, InputParameters *params)
 {
-  put_buffer_frame ();
-
-  snr->snr_y = snr_field_y;
-  snr->snr_u = snr_field_u;
-  snr->snr_v = snr_field_v;
+  put_buffer_frame (img);
 }
 
 
@@ -1168,9 +1080,9 @@ static void field_mode_buffer (int bit_field, float snr_field_y, float snr_field
  *    Frame Mode Buffer
  ************************************************************************
  */
-static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v)
+static void frame_mode_buffer (ImageParameters *img, InputParameters *params)
 {
-  put_buffer_frame ();
+  put_buffer_frame (img);
 
   if ((params->PicInterlace != FRAME_CODING)||(params->MbInterlace != FRAME_CODING))
   {
@@ -1178,20 +1090,16 @@ static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame
     img->height_cr = img->height_cr / 2;
     img->number *= 2;
 
-    put_buffer_top ();
+    put_buffer_top (img);
 
     img->number++;
-    put_buffer_bot ();
+    put_buffer_bot (img);
 
     img->number /= 2;         // reset the img->number to field
     img->height = (params->output.height + img->auto_crop_bottom);
     img->height_cr = img->height_cr_frame;
 
-    snr->snr_y = snr_frame_y;
-    snr->snr_u = snr_frame_u;
-    snr->snr_v = snr_frame_v;
-    put_buffer_frame ();
-
+    put_buffer_frame (img);
   }
 }
 
@@ -1214,7 +1122,7 @@ static void init_dec_ref_pic_marking_buffer(void)
  *    Initializes the parameters for a new frame
  ************************************************************************
  */
-static void init_frame (void)
+static void init_frame (ImageParameters *img)
 {
   int i, j;
   int prevP_no, nextP_no;
@@ -1242,16 +1150,13 @@ static void init_frame (void)
   else
   {
     for(i=0;i< ((int) (img->FrameSizeInMbs));i++)
-      img->mb_data[i].slice_nr=-1;
+      img->mb_data[i].slice_nr = -1;
   }
 
   if (img->b_frame_to_code == 0)
   {
     img->tr = start_tr_in_this_IGOP + IMG_NUMBER * (params->jumpd + 1);
 
-    img->imgtr_last_P_frm = img->imgtr_next_P_frm;
-    img->imgtr_next_P_frm = img->tr;
-
 #ifdef _ADAPT_LAST_GROUP_
     if (params->last_frame && img->frm_number + 1 == params->no_frames)
       img->tr = params->last_frame;
@@ -1405,7 +1310,7 @@ static void init_frame (void)
  *    Initializes the parameters for a new field
  ************************************************************************
  */
-static void init_field (void)
+static void init_field (ImageParameters *img)
 {
   int i;
   int prevP_no, nextP_no;
@@ -1429,12 +1334,6 @@ static void init_field (void)
   {
     img->tr = img->number * (params->jumpd + 2) + img->fld_type;
 
-    if (!img->fld_type)
-    {
-      img->imgtr_last_P_fld = img->imgtr_next_P_fld;
-      img->imgtr_next_P_fld = img->tr;
-    }
-
 #ifdef _ADAPT_LAST_GROUP_
     if (params->last_frame && img->number + 1 == params->no_frames)
       img->tr = params->last_frame;
@@ -1494,6 +1393,7 @@ static void init_field (void)
     img->p_interval = params->jumpd + 2;
     prevP_no = (img->number - 1) * img->p_interval + img->fld_type;
     nextP_no = img->number * img->p_interval + img->fld_type;
+
 #ifdef _ADAPT_LAST_GROUP_
     if (!img->fld_type)       // top field
     {
@@ -1522,6 +1422,7 @@ static void init_field (void)
       img->p_interval = nextP_no - prevP_no;
     }
 #endif
+
     img->b_interval =
       ((double) (params->jumpd + 1) / (params->successive_Bframe + 1.0) );
 
@@ -1551,6 +1452,7 @@ static void init_field (void)
         img->qp = params->qpB;
       if (img->nal_reference_idc)
       {
+
 #ifdef _CHANGE_QP_
         //QP oscillation for secondary SP frames
         if ((params->qp2start > 0 && img->tr >= params->qp2start && params->sp2_frame_indicator==0)||
@@ -1711,203 +1613,6 @@ void UnifiedOneForthPix_JV (int nplane, StorablePicture *s)
   getSubImagesLuma ( s );
 }
 
-/*!
- ************************************************************************
- * \brief
- *    Find SNR for all three components
- ************************************************************************
- */
-static void find_snr (void)
-{
-  int i;
-  imgpel **curCmp = pCurImg, **curRef = imgY_com;
-
-  int64 diff_cmp[3] = {0};
-  int impix    = params->output.size_cmp[0];
-  int impix_cr = params->output.size_cmp[1];
-  unsigned int max_pix_value_sqd = img->max_imgpel_value_comp[0] * img->max_imgpel_value_comp[0];
-  unsigned int max_pix_value_sqd_uv = img->max_imgpel_value_comp[1] * img->max_imgpel_value_comp[1];
-
-  //  Calculate  PSNR for Y, U and V.
-  //     Luma.
-  if (img->fld_flag != 0)
-  {
-    diff_cmp[0] += compute_SSE(curCmp, curRef, 0, 0, params->output.height, params->output.width);
-
-    if (img->yuv_format != YUV400)
-    {
-      //     Chroma.
-      diff_cmp[1] += compute_SSE(imgUV_org[0], imgUV_com[0], 0, 0, params->output.height_cr, params->output.width_cr);
-      diff_cmp[2] += compute_SSE(imgUV_org[1], imgUV_com[1], 0, 0, params->output.height_cr, params->output.width_cr);
-    }
-  }
-  else
-  {
-    if( IS_INDEPENDENT(params) )
-    {
-      pCurImg = imgY_org_frm_JV[0];
-    }
-    else
-    {
-      pCurImg  = imgY_org_frm;
-      imgUV_org = imgUV_org_frm;
-      pImgOrg[0] = imgY_org_frm;
-    }
-
-    curCmp = pCurImg;
-    if(params->PicInterlace==ADAPTIVE_CODING || IS_INDEPENDENT(params))
-    {
-      enc_picture = enc_frame_picture[0];
-    }
-    curRef = enc_picture->imgY;
-
-    diff_cmp[0] += compute_SSE(curCmp, curRef, 0, 0, params->output.height, params->output.width);
-
-    if (img->yuv_format != YUV400)
-    {
-      //     Chroma.
-      if( !IS_INDEPENDENT(params) )
-      {      
-        pImgOrg[1] = imgUV_org_frm[0];
-        pImgOrg[2] = imgUV_org_frm[1];
-      }    
-      diff_cmp[1] += compute_SSE(pImgOrg[1], enc_picture->imgUV[0], 0, 0, params->output.height_cr, params->output.width_cr);
-      diff_cmp[2] += compute_SSE(pImgOrg[2], enc_picture->imgUV[1], 0, 0, params->output.height_cr, params->output.width_cr);
-    }
-  }
-  snr->sse_y = (float)diff_cmp[0];
-  snr->sse_u = (float)diff_cmp[1];
-  snr->sse_v = (float)diff_cmp[2];
-
-#if ZEROSNR
-  if (diff_cmp[0] == 0)
-    diff_cmp[0] = 1;
-  if (diff_cmp[1] == 0)
-    diff_cmp[1] = 1;
-  if (diff_cmp[2] == 0)
-    diff_cmp[2] = 1;
-#endif
-
-  //  Collecting SNR statistics
-  if (diff_cmp[0] != 0)
-  {
-    snr->snr_y = (float) (10 * log10 (max_pix_value_sqd * (double)((double) impix    / diff_cmp[0])));         // luma snr for current frame
-    if (img->yuv_format != YUV400)
-    {
-      snr->snr_u = (float) (10 * log10 (max_pix_value_sqd_uv * (double)((double) impix_cr / diff_cmp[1])));   // u croma snr for current frame, 1/4 of luma samples
-      snr->snr_v = (float) (10 * log10 (max_pix_value_sqd_uv * (double)((double) impix_cr / diff_cmp[2])));   // v croma snr for current frame, 1/4 of luma samples
-    }
-    else
-    {
-      snr->snr_u = 0.0;
-      snr->snr_v = 0.0;
-    }
-  }
-
-
-  if (img->number == 0)
-  {
-    snr->snr_y1 = snr->snr_y;  // keep luma snr for first frame
-    snr->snr_u1 = snr->snr_u;  // keep croma u snr for first frame
-    snr->snr_v1 = snr->snr_v;  // keep croma v snr for first frame
-    snr->snr_ya = snr->snr_y1;
-    snr->snr_ua = snr->snr_u1;
-    snr->snr_va = snr->snr_v1;
-    // sse stats
-    snr->msse_y = snr->sse_y;
-    snr->msse_u = snr->sse_u;
-    snr->msse_v = snr->sse_v;
-    for (i=0; i<5; i++)
-    {
-      snr->snr_yt[i] = 0.0;
-      snr->snr_ut[i] = 0.0;
-      snr->snr_vt[i] = 0.0;
-    }
-  }
-  else
-  {
-    //int total_frames = img->number + frame_ctr[B_SLICE];
-    int total_frames = snr->frame_ctr - 1;
-
-    snr->snr_ya = (float) (snr->snr_ya * total_frames + snr->snr_y) / (total_frames + 1); // average snr luma for all frames inc. first
-    snr->snr_ua = (float) (snr->snr_ua * total_frames + snr->snr_u) / (total_frames + 1); // average snr u croma for all frames inc. first
-    snr->snr_va = (float) (snr->snr_va * total_frames + snr->snr_v) / (total_frames + 1); // average snr v croma for all frames inc. first
-    snr->msse_y = (float) (snr->msse_y * total_frames + snr->sse_y) / (total_frames + 1); // average sse luma for all frames inc. first
-    snr->msse_u = (float) (snr->msse_u * total_frames + snr->sse_u) / (total_frames + 1); // average sse u croma for all frames inc. first
-    snr->msse_v = (float) (snr->msse_v * total_frames + snr->sse_v) / (total_frames + 1); // average sse v croma for all frames inc. first
-  }
-
-  snr->snr_yt[img->type] = (float) (snr->snr_yt[img->type] * (frame_ctr[img->type] - 1) + snr->snr_y) / ( frame_ctr[img->type] );  // average luma snr for img->type coded frames
-  snr->snr_ut[img->type] = (float) (snr->snr_ut[img->type] * (frame_ctr[img->type] - 1) + snr->snr_u) / ( frame_ctr[img->type] );  // average chroma u snr for img->type coded frames
-  snr->snr_vt[img->type] = (float) (snr->snr_vt[img->type] * (frame_ctr[img->type] - 1) + snr->snr_v) / ( frame_ctr[img->type] );  // average chroma v snr for img->type coded frames
-}
-
-
-
-/*!
- ************************************************************************
- * \brief
- *    Find distortion for all three components
- ************************************************************************
- */
-static void find_distortion (void)
-{
-  int64 diff_cmp[3] = {0};
-
-  //  Calculate  PSNR for Y, U and V.
-
-  //     Luma.
-  if (img->structure!=FRAME)
-  {
-    diff_cmp[0] += compute_SSE(pCurImg, imgY_com, 0, 0, params->output.height, params->output.width);
-
-    if (img->yuv_format != YUV400)
-    {
-      //     Chroma.
-      diff_cmp[1] += compute_SSE(imgUV_org[0], imgUV_com[0], 0, 0, params->output.height_cr, params->output.width_cr);
-      diff_cmp[2] += compute_SSE(imgUV_org[1], imgUV_com[1], 0, 0, params->output.height_cr, params->output.width_cr);
-    }
-  }
-  else
-  {
-    if( IS_INDEPENDENT(params) )
-    {
-      pCurImg   = imgY_org_frm_JV[0];
-      enc_picture = enc_frame_picture[0];
-      pImgOrg[0] = imgY_org_frm_JV[0];  
-    }
-    else
-    {
-      pCurImg  = imgY_org_frm;
-      imgUV_org = imgUV_org_frm;
-      pImgOrg[0] = imgY_org_frm;
-    }
-
-    diff_cmp[0] += compute_SSE(pCurImg, enc_picture->imgY, 0, 0, params->output.height, params->output.width);
-
-    if (img->yuv_format != YUV400)
-    {
-      //     Chroma.
-      if( IS_INDEPENDENT(params) )
-      {
-        pImgOrg[1] = imgY_org_frm_JV[1];
-        pImgOrg[2] = imgY_org_frm_JV[2];  
-      }
-      else
-      {      
-        pImgOrg[1] = imgUV_org_frm[0];
-        pImgOrg[2] = imgUV_org_frm[1];
-      }
-
-      diff_cmp[1] += compute_SSE(pImgOrg[1], enc_picture->imgUV[0], 0, 0, params->output.height_cr, params->output.width_cr);
-      diff_cmp[2] += compute_SSE(pImgOrg[2], enc_picture->imgUV[1], 0, 0, params->output.height_cr, params->output.width_cr);
-    }
-  }
-  // Calculate real PSNR at find_snr_avg()
-  snr->snr_y = (float) diff_cmp[0];
-  snr->snr_u = (float) diff_cmp[1];
-  snr->snr_v = (float) diff_cmp[2];
-}
 
 
   /*!
@@ -1922,6 +1627,13 @@ Boolean dummy_slice_too_big (int bits_slice)
 }
 
 
+static inline void copy_motion_vectors_MB (ImageParameters *img, RD_DATA *rdopt)
+{
+  memcpy(&img->all_mv [LIST_0][0][0][0][0][0], &rdopt->all_mv [LIST_0][0][0][0][0][0], 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short));  
+  memcpy(&img->pred_mv[LIST_0][0][0][0][0][0], &rdopt->pred_mv[LIST_0][0][0][0][0][0], 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short));
+}
+
+
 /*!
 ***************************************************************************
 // For MB level field/frame coding
@@ -1942,7 +1654,6 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
   currMB->mb_type     = rdopt->mb_type;    // copy mb_type
   currMB->cbp         = rdopt->cbp;        // copy cbp
   currMB->cbp_blk     = rdopt->cbp_blk;    // copy cbp_blk
-  currMB->bi_pred_me  = rdopt->bi_pred_me; // copy biprediction
   img->i16offset      = rdopt->i16offset;
 
   currMB->prev_qp  = rdopt->prev_qp;
@@ -1950,7 +1661,7 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
   currMB->prev_cbp = rdopt->prev_cbp;
   currMB->delta_qp = rdopt->delta_qp;
   currMB->qp       = rdopt->qp;
-  update_qp(currMB);
+  update_qp (img, currMB);
 
   currMB->c_ipred_mode = rdopt->c_ipred_mode;
 
@@ -1960,20 +1671,20 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
   for (j = 0; j < BLOCK_MULTIPLE; j++)
   {
     block_y = img->block_y + j;
-    memcpy(&enc_picture->ref_idx[LIST_0][block_y][img->block_x], rdopt->refar[LIST_0][j], BLOCK_MULTIPLE * sizeof(char));
+    memcpy(&enc_picture->motion.ref_idx[LIST_0][block_y][img->block_x], rdopt->refar[LIST_0][j], BLOCK_MULTIPLE * sizeof(char));
     for (i = 0; i < BLOCK_MULTIPLE; i++)
-      enc_picture->ref_pic_id [LIST_0][block_y][img->block_x + i] =
-      enc_picture->ref_pic_num[LIST_0 + list_offset][(short)enc_picture->ref_idx[LIST_0][block_y][img->block_x+i]];
+      enc_picture->motion.ref_pic_id [LIST_0][block_y][img->block_x + i] =
+      enc_picture->ref_pic_num[LIST_0 + list_offset][(short)enc_picture->motion.ref_idx[LIST_0][block_y][img->block_x+i]];
   }
   if (bframe)
   {
     for (j = 0; j < BLOCK_MULTIPLE; j++)
     {
       block_y = img->block_y + j;
-      memcpy(&enc_picture->ref_idx[LIST_1][block_y][img->block_x], rdopt->refar[LIST_1][j], BLOCK_MULTIPLE * sizeof(char));
+      memcpy(&enc_picture->motion.ref_idx[LIST_1][block_y][img->block_x], rdopt->refar[LIST_1][j], BLOCK_MULTIPLE * sizeof(char));
       for (i = 0; i < BLOCK_MULTIPLE; i++)
-        enc_picture->ref_pic_id [LIST_1][block_y][img->block_x + i] =
-        enc_picture->ref_pic_num[LIST_1 + list_offset][(short)enc_picture->ref_idx[LIST_1][block_y][img->block_x+i]];
+        enc_picture->motion.ref_pic_id [LIST_1][block_y][img->block_x + i] =
+        enc_picture->ref_pic_num[LIST_1 + list_offset][(short)enc_picture->motion.ref_idx[LIST_1][block_y][img->block_x + i]];
     }
   }
 
@@ -1985,13 +1696,13 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
   {
     for (j = 0; j < img->mb_cr_size_y; j++)
     {
-      memcpy(&enc_picture->imgUV[0][img->pix_c_y + j][img->pix_c_x],rdopt->rec_mb_cr[0][j], img->mb_cr_size_x * sizeof(imgpel));
-      memcpy(&enc_picture->imgUV[1][img->pix_c_y + j][img->pix_c_x],rdopt->rec_mb_cr[1][j], img->mb_cr_size_x * sizeof(imgpel));
+      memcpy(&enc_picture->imgUV[0][img->pix_c_y + j][img->pix_c_x], rdopt->rec_mb_cr[0][j], img->mb_cr_size_x * sizeof(imgpel));
+      memcpy(&enc_picture->imgUV[1][img->pix_c_y + j][img->pix_c_x], rdopt->rec_mb_cr[1][j], img->mb_cr_size_x * sizeof(imgpel));
     }
   }
 
-  memcpy(currMB->b8mode,rdopt->b8mode, 4 * sizeof(short));
-  memcpy(currMB->b8pdir,rdopt->b8pdir, 4 * sizeof(short));
+  memcpy(currMB->b8mode, rdopt->b8mode, 4 * sizeof(short));
+  memcpy(currMB->b8pdir, rdopt->b8pdir, 4 * sizeof(short));
 
 
   currMB->luma_transform_size_8x8_flag = rdopt->luma_transform_size_8x8_flag;
@@ -2022,7 +1733,7 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
   if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
   {
     // motion vectors
-    copy_motion_vectors_MB ();
+    copy_motion_vectors_MB (img, rdopt);
 
     if (!IS_INTRA(currMB))
     {
@@ -2034,25 +1745,25 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
 
           if (b8pdir!=1)
           {
-            enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][j][i][0];
-            enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][j][i][1];
+            enc_picture->motion.mv[LIST_0][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][j][i][0];
+            enc_picture->motion.mv[LIST_0][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][j][i][1];
           }
           else
           {
-            enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][0] = 0;
-            enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][1] = 0;
+            enc_picture->motion.mv[LIST_0][j+img->block_y][i+img->block_x][0] = 0;
+            enc_picture->motion.mv[LIST_0][j+img->block_y][i+img->block_x][1] = 0;
           }
           if (bframe)
           {
             if (b8pdir!=0)
             {
-              enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][j][i][0];
-              enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][j][i][1];
+              enc_picture->motion.mv[LIST_1][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][j][i][0];
+              enc_picture->motion.mv[LIST_1][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][j][i][1];
             }
             else
             {
-              enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][0] = 0;
-              enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][1] = 0;
+              enc_picture->motion.mv[LIST_1][j+img->block_y][i+img->block_x][0] = 0;
+              enc_picture->motion.mv[LIST_1][j+img->block_y][i+img->block_x][1] = 0;
             }
           }
         }
@@ -2060,26 +1771,19 @@ void copy_rdopt_data (Macroblock *currMB, int bot_block)
     else
     {
       for (j = 0; j < 4; j++)
-        memset(enc_picture->mv[LIST_0][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
+        memset(enc_picture->motion.mv[LIST_0][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
       if (bframe)
       {
         for (j = 0; j < 4; j++)
-          memset(enc_picture->mv[LIST_1][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
+          memset(enc_picture->motion.mv[LIST_1][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
       }
     }
   }
-}                             // end of copy_rdopt_data
+} // end of copy_rdopt_data
 
-static void copy_motion_vectors_MB (void)
-{
-  memcpy(&img->all_mv[LIST_0][0][0][0][0][0], &rdopt->all_mv[LIST_0][0][0][0][0][0], 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short));
-  
-  memcpy(&img->pred_mv[LIST_0][0][0][0][0][0], &rdopt->pred_mv[LIST_0][0][0][0][0][0], 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short));
-}
 
 static void ReportNALNonVLCBits(time_t tmp_time, time_t me_time)
 {
-
   //! Need to add type (i.e. SPS, PPS, SEI etc).
   if (params->Verbose != 0)
   printf ("%04d(NVB)%8d \n", frame_no, stats->bit_ctr_parametersets_n);
@@ -2091,19 +1795,25 @@ static void ReportFirstframe(time_t tmp_time, time_t me_time)
   {
     printf ("%04d(IDR)%8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-      img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
   }
   else if (params->Verbose == 2)
   {
     int lambda = (int) img->lambda_me[I_SLICE][img->AverageFrameQP][0];
-    printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+    if (params->Distortion[SSIM] == 1)
+      printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+      frame_no,(int) (stats->bit_ctr - stats->bit_ctr_n),0,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    else
+      printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
       frame_no,(int) (stats->bit_ctr - stats->bit_ctr_n),0,
-      img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
   }
 
-  stats->bit_ctr_I = stats->bit_ctr;
+  stats->bit_counter[I_SLICE] = stats->bit_ctr;
   stats->bit_ctr = 0;
 }
 
@@ -2111,31 +1821,48 @@ static void ReportIntra(time_t tmp_time, time_t me_time)
 {
   if (params->Verbose == 1)
   {
-   if (img->currentPicture->idr_flag == 1)
+    if (img->currentPicture->idr_flag == 1)
       printf ("%04d(IDR)%8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-      img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
     else
       printf ("%04d(I)  %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-      img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
   }
   else if (params->Verbose == 2)
   {
     int lambda = (int) img->lambda_me[I_SLICE][img->AverageFrameQP][0];
-    if (img->currentPicture->idr_flag == 1)
-      printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
-      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
-      img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
-      img->fld_flag ? "FLD" : "FRM", intras, 
-      img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    if (params->Distortion[SSIM] == 1)
+    {
+      if (img->currentPicture->idr_flag == 1)
+        printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+        frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
+        img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+        img->fld_flag ? "FLD" : "FRM", intras, 
+        img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+      else
+        printf ("%04d(I)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+        frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
+        img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+        img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    }
     else
-      printf ("%04d(I)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
-      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
-      img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
-      img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    {
+      if (img->currentPicture->idr_flag == 1)
+        printf ("%04d(IDR)%8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+        frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
+        img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
+        img->fld_flag ? "FLD" : "FRM", intras, 
+        img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+      else
+        printf ("%04d(I)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+        frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), 0,
+        img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
+        img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    }
   }
 }
 
@@ -2145,15 +1872,21 @@ static void ReportSP(time_t tmp_time, time_t me_time)
   {
     printf ("%04d(SP) %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-      img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
   }
   else if (params->Verbose == 2)
   {
     int lambda = (int) img->lambda_me[SP_SLICE][img->AverageFrameQP][0];    
-    printf ("%04d(SP) %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+    if (params->Distortion[SSIM] == 1)
+      printf ("%04d(SP) %8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_pred_flag,
-      img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    else
+      printf ("%04d(SP) %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_pred_flag,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
   }
 }
@@ -2163,18 +1896,26 @@ static void ReportB(time_t tmp_time, time_t me_time)
   if (params->Verbose == 1)
   {
     printf ("%04d(B)  %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
-    frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-    img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
-    img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
+      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
+      img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
   }
   else if (params->Verbose == 2)
   {
     int lambda = (int) img->lambda_me[img->nal_reference_idc ? 5 : B_SLICE][img->AverageFrameQP][0];    
-    printf ("%04d(B)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d %1d %2d %2d  %d   %d\n",
-    frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_bipred_idc,
-    img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
-    img->fld_flag ? "FLD" : "FRM",intras,img->direct_spatial_mv_pred_flag, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc);
+    if (params->Distortion[SSIM] == 1)
+      printf ("%04d(B)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d %1d %2d %2d  %d   %d\n",
+      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_bipred_idc,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", intras, img->direct_spatial_mv_pred_flag, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active, img->rd_pass, img->nal_reference_idc);
+    else
+      printf ("%04d(B)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d %1d %2d %2d  %d   %d\n",
+      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_bipred_idc,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", intras, img->direct_spatial_mv_pred_flag, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active, img->rd_pass, img->nal_reference_idc);
   }
+
+
 }
 
 
@@ -2186,7 +1927,7 @@ static void ReportP(time_t tmp_time, time_t me_time)
     {
       printf ("%04d(P)  %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
         frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-        img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+        img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
         img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
     }
     else
@@ -2195,14 +1936,14 @@ static void ReportP(time_t tmp_time, time_t me_time)
       {
         printf ("%04d(P)  %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
           frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n),
-          img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+          img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
           img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
       }
       else
       { // report a redundant picture.
         printf ("    (R)  %8d   %2d %7.3f %7.3f %7.3f %9d %7d    %3s    %d\n",
           (int) (stats->bit_ctr - stats->bit_ctr_n),
-          img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+          img->AverageFrameQP, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
           img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc);
       }
     }
@@ -2210,9 +1951,15 @@ static void ReportP(time_t tmp_time, time_t me_time)
   else if (params->Verbose == 2)
   {
     int lambda = (int) img->lambda_me[P_SLICE][img->AverageFrameQP][0];    
-    printf ("%04d(P)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+    if (params->Distortion[SSIM] == 1)
+      printf ("%04d(P)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %7.4f %7.4f %7.4f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
+      frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_pred_flag,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], dist->metric[SSIM].value[0], dist->metric[SSIM].value[1], dist->metric[SSIM].value[2], (int)tmp_time, (int)me_time,
+      img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active, img->rd_pass, img->nal_reference_idc);
+    else
+      printf ("%04d(P)  %8d %1d %2d %2d %7.3f %7.3f %7.3f %9d %7d    %3s %5d   %2d %2d  %d   %d\n",
       frame_no, (int) (stats->bit_ctr - stats->bit_ctr_n), active_pps->weighted_pred_flag,
-      img->AverageFrameQP, lambda, snr->snr_y, snr->snr_u, snr->snr_v, (int)tmp_time, (int)me_time,
+      img->AverageFrameQP, lambda, dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2], (int)tmp_time, (int)me_time,
       img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active, img->rd_pass, img->nal_reference_idc);
   }
 }
@@ -2223,18 +1970,12 @@ static void ReportP(time_t tmp_time, time_t me_time)
  *    Padding of automatically added border for picture sizes that are not
  *     multiples of macroblock/macroblock pair size
  *
- * \param org_size_x
- *    original image horizontal size (luma)
- * \param org_size_y
- *    original image vertical size (luma)
+ * \param output
+ *    Image dimensions
  * \param img_size_x
  *    coded image horizontal size (luma)
  * \param img_size_y
  *    code image vertical size (luma)
- * \param org_size_x_cr
- *    original image horizontal size (chroma)
- * \param org_size_y_cr
- *    original image vertical size (chroma)
  * \param img_size_x_cr
  *    coded image horizontal size (chroma)
  * \param img_size_y_cr
@@ -2255,8 +1996,7 @@ static void PaddAutoCropBorders (FrameFormat output, int img_size_x, int img_siz
   //padding bottom border
   if (output.height < img_size_y)
     for (y = output.height; y<img_size_y; y++)
-      for (x=0; x<img_size_x; x++)
-        pImgOrg[0] [y][x] = pImgOrg[0] [y-1][x];
+      memcpy(pImgOrg[0][y], pImgOrg[0][y - 1], img_size_x * sizeof(imgpel));
 
   // Chroma or all other components
   if (img->yuv_format != YUV400)
@@ -2274,8 +2014,7 @@ static void PaddAutoCropBorders (FrameFormat output, int img_size_x, int img_siz
       //padding bottom border
       if (output.height_cr < img_size_y_cr)
         for (y = output.height_cr; y<img_size_y_cr; y++)
-          for (x=0; x<img_size_x_cr; x++)
-            pImgOrg[k][y][x] = pImgOrg[k][y-1][x];
+          memcpy(pImgOrg[k][y], pImgOrg[k][y - 1], img_size_x_cr * sizeof(imgpel));
     }
   }
 }
@@ -2329,7 +2068,7 @@ int CalculateFrameNumber(void)
 
     frame_no = start_tr_in_this_IGOP + (frm_sign * IMG_NUMBER + delay) * (params->jumpd + 1);     
 #ifdef _ADAPT_LAST_GROUP_
-    if (params->last_frame && img->frm_number + 1 == params->no_frames)
+    if (params->last_frame && (img->frm_number + 1) == params->no_frames)
       frame_no = params->last_frame;
 #endif
   }
@@ -2346,28 +2085,14 @@ int CalculateFrameNumber(void)
  *    point to frame coding variables
  ************************************************************************
  */
-static void put_buffer_frame(void)
+static void put_buffer_frame(ImageParameters *img)
 {
-  if( IS_INDEPENDENT(params) )
-  {
-    pImgOrg[0] = imgY_org_frm_JV[0];
-    pCurImg    = pImgOrg[0];
-    if (img->yuv_format != YUV400)
-    {
-      pImgOrg[1] = imgY_org_frm_JV[1];
-      pImgOrg[2] = imgY_org_frm_JV[2];
-    }
-  }
-  else
+  pCurImg    = img_org_frm[0];
+  pImgOrg[0] = img_org_frm[0];    
+  if (img->yuv_format != YUV400)
   {
-    pCurImg    = imgY_org_frm;
-    imgUV_org  = imgUV_org_frm;
-    pImgOrg[0] = imgY_org_frm;
-    if (img->yuv_format != YUV400)
-    {
-      pImgOrg[1] = imgUV_org_frm[0];
-      pImgOrg[2] = imgUV_org_frm[1];
-    }
+    pImgOrg[1] = img_org_frm[1];
+    pImgOrg[2] = img_org_frm[2];
   }
 }
 
@@ -2377,17 +2102,16 @@ static void put_buffer_frame(void)
  *    point to top field coding variables
  ************************************************************************
  */
-static void put_buffer_top(void)
+static void put_buffer_top(ImageParameters *img)
 {
   img->fld_type = 0;
 
-  pCurImg    = imgY_org_top;
-  imgUV_org  = imgUV_org_top;
-  pImgOrg[0] = imgY_org_top;
+  pCurImg    = img_org_top[0];
+  pImgOrg[0] = img_org_top[0];
   if (img->yuv_format != YUV400)
   {
-    pImgOrg[1] = imgUV_org_top[0];
-    pImgOrg[2] = imgUV_org_top[1];
+    pImgOrg[1] = img_org_top[1];
+    pImgOrg[2] = img_org_top[2];
   }
 }
 
@@ -2397,17 +2121,16 @@ static void put_buffer_top(void)
  *    point to bottom field coding variables
  ************************************************************************
  */
-static void put_buffer_bot(void)
+static void put_buffer_bot(ImageParameters *img)
 {
   img->fld_type = 1;
 
-  pCurImg    = imgY_org_bot;
-  imgUV_org  = imgUV_org_bot;
-  pImgOrg[0] = imgY_org_bot;
+  pCurImg    = img_org_bot[0];  
+  pImgOrg[0] = img_org_bot[0];
   if (img->yuv_format != YUV400)
   {
-    pImgOrg[1] = imgUV_org_bot[0];
-    pImgOrg[2] = imgUV_org_bot[1];
+    pImgOrg[1] = img_org_bot[1];
+    pImgOrg[2] = img_org_bot[2];
   }
 }
 
@@ -2502,15 +2225,21 @@ static void rdPictureCoding(void)
 
   if ( params->RCEnable )
     rc_save_state();
+  if ( params->WPMCPrecision )
+    pWPX->curr_wp_rd_pass = pWPX->wp_rd_passes + 1;
 
   if (img->type!=I_SLICE && params->GenerateMultiplePPS)
   {
     if (img->type==P_SLICE)
     {
-      if ((params->RDPSliceWeightOnly != 2) && (TestWPPSlice(0) == 1))
+      if ((params->RDPSliceWeightOnly != 2) && (TestWPPSlice(img, params, 0) == 1))
       {
         active_pps = PicParSet[1];
+        if ( params->WPMCPrecision )
+          pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
       }
+      else if ( params->WPMCPrecision )
+        active_pps = PicParSet[1];
       else
       {
         skip_encode = params->RDPSliceWeightOnly;
@@ -2526,6 +2255,8 @@ static void rdPictureCoding(void)
     else
     {
       active_pps = PicParSet[2];
+      if ( params->WPMCPrecision )
+        pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
     }
   }
   else
@@ -2564,12 +2295,12 @@ static void rdPictureCoding(void)
     enc_picture=enc_frame_picture[0];
     if (img->type!=I_SLICE && params->GenerateMultiplePPS)
     {
-      img->qp=rd_qp;
+      img->qp = rd_qp;
       active_pps = PicParSet[0];
     }
     else
     {
-      img->qp=rd_qp;
+      img->qp = rd_qp;
     }
     intras = previntras;
     p_frame_pic = frame_pic[0];
@@ -2588,7 +2319,9 @@ static void rdPictureCoding(void)
   if ( params->RCEnable )
     rateRatio = 1.0F;
 
-  if (img->type!=I_SLICE )
+  if ( params->WPMCPrecision )
+    pWPX->curr_wp_rd_pass = pWPX->wp_rd_passes + 2;
+  if (img->type != I_SLICE )
   {
     skip_encode = 0;
     img->qp    = rd_qp;
@@ -2602,10 +2335,14 @@ static void rdPictureCoding(void)
     {
       if (params->GenerateMultiplePPS)
       {
-        if ((params->RDPSliceWeightOnly != 2) && (TestWPPSlice(0) == 1))
+        if ((params->RDPSliceWeightOnly != 2) && (TestWPPSlice(img, params, 0) == 1))
         {
           active_pps = PicParSet[1];
+          if ( params->WPMCPrecision )
+            pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
         }
+        else if ( params->WPMCPrecision == 2 )
+          active_pps = PicParSet[1];
         else if (params->RDPSliceBTest && active_sps->profile_idc != 66)
         {
           set_slice_type( B_SLICE );
@@ -2626,16 +2363,22 @@ static void rdPictureCoding(void)
     }
     else
     {
-      if (params->GenerateMultiplePPS && (params->RDBSliceWeightOnly != 2) && TestWPBSlice(0) == 1)
+      if (params->GenerateMultiplePPS && (params->RDBSliceWeightOnly != 2) && TestWPBSlice(img, params, 0) == 1)
       {
         active_pps = PicParSet[1];
+        if ( params->WPMCPrecision )
+          pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
       }
+      else if ( params->WPMCPrecision == 2 && (params->WPMCPrecBSlice == 2 || (params->WPMCPrecBSlice == 1 && img->nal_reference_idc) ) )
+        active_pps = PicParSet[1];
       else
       {
         skip_encode = (params->RDBSliceWeightOnly == 1);
         img->qp = rd_qp + (img->nal_reference_idc ? - 1 : 1);
         if ( params->RCEnable )
           rateRatio = img->nal_reference_idc ? 1.15F : 0.85F;
+        if ( params->WPMCPrecision )
+          pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
       }
     }
   }
@@ -2809,7 +2552,7 @@ void select_plane(ColorPlane color_plane)
   enc_picture->p_curr_img_sub = enc_picture->p_img_sub[color_plane];
   img->max_imgpel_value       = img->max_imgpel_value_comp[color_plane];
   img->dc_pred_value          = img->dc_pred_value_comp[color_plane];
-  img->curr_res               = img->m7[color_plane];
-  img->curr_prd               = img->mpr[color_plane];
+  img->curr_res               = img->mb_rres [color_plane];
+  img->curr_prd               = img->mb_pred [color_plane];
 }
 
diff --git a/lencod/src/img_dist_ms_ssim.c b/lencod/src/img_dist_ms_ssim.c
new file mode 100644
index 0000000..8ef6ac1
--- /dev/null
+++ b/lencod/src/img_dist_ms_ssim.c
@@ -0,0 +1,353 @@
+
+/*!
+ *************************************************************************************
+ * \file img_dist_ms_ssim.c
+ *
+ * \brief
+ *    Compute structural similarity (SSIM) index using the encoded image and the reference image
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Peshala Pahalawatta             <ppaha@dolby.com>
+ *     - Zhen Li                         <zli@dolby.com> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *************************************************************************************
+ */
+#include "contributors.h"
+#include "global.h"
+#include "img_distortion.h"
+#include "enc_statistics.h"
+#include "memalloc.h"
+#include "math.h"
+
+#ifndef UNBIASED_VARIANCE
+  #define UNBIASED_VARIANCE // unbiased estimation of the variance
+#endif
+
+#define MS_SSIM_PAD  6
+#define MS_SSIM_PAD2 3
+
+#define MS_SSIM_BETA0 0.0448
+#define MS_SSIM_BETA1 0.2856
+#define MS_SSIM_BETA2 0.3001
+#define MS_SSIM_BETA3 0.2363
+#define MS_SSIM_BETA4 0.1333
+
+#define MAX_SSIM_LEVELS 5
+
+//Computes the product of the contrast and structure componenents of the structural similarity metric.
+float compute_structural_components (imgpel **refImg, imgpel **encImg, int height, int width, int win_height, int win_width, int comp)
+{
+  static const float K2 = 0.03f;
+  static float max_pix_value_sqd;
+  float C2;
+  float win_pixels = (float) (win_width * win_height);
+#ifdef UNBIASED_VARIANCE
+  float win_pixels_bias = win_pixels - 1;
+#else
+  float win_pixels_bias = win_pixels;
+#endif
+  float mb_ssim, meanOrg, meanEnc;
+  float varOrg, varEnc, covOrgEnc;
+  int imeanOrg, imeanEnc, ivarOrg, ivarEnc, icovOrgEnc;
+  float cur_distortion = 0.0;
+  int i, j, n, m, win_cnt = 0;
+  int overlapSize = params->SSIMOverlapSize;
+
+  max_pix_value_sqd = (float) (img->max_imgpel_value_comp[comp] * img->max_imgpel_value_comp[comp]);
+  C2 = K2 * K2 * max_pix_value_sqd;
+
+  for (j = 0; j <= height - win_height; j += overlapSize)
+  {
+    for (i = 0; i <= width - win_width; i += overlapSize)
+    {
+      imeanOrg = 0;
+      imeanEnc = 0; 
+      ivarOrg  = 0;
+      ivarEnc  = 0;
+      icovOrgEnc = 0;
+
+      for ( n = j;n < j + win_height;n ++)
+      {
+        for (m = i;m < i + win_width;m ++)
+        {
+          imeanOrg   += refImg[n][m];
+          imeanEnc   += encImg[n][m];
+          ivarOrg    += refImg[n][m] * refImg[n][m];
+          ivarEnc    += encImg[n][m] * encImg[n][m];
+          icovOrgEnc += refImg[n][m] * encImg[n][m];
+        }
+      }
+
+      meanOrg = (float) imeanOrg / win_pixels;
+      meanEnc = (float) imeanEnc / win_pixels;
+
+      varOrg    = ((float) ivarOrg - ((float) imeanOrg) * meanOrg) / win_pixels_bias;
+      varEnc    = ((float) ivarEnc - ((float) imeanEnc) * meanEnc) / win_pixels_bias;
+      covOrgEnc = ((float) icovOrgEnc - ((float) imeanOrg) * meanEnc) / win_pixels_bias;
+
+      mb_ssim  = (float) (2.0 * covOrgEnc + C2);
+      mb_ssim /= (float) (varOrg + varEnc + C2);
+
+      cur_distortion += mb_ssim;
+      win_cnt++;
+    }
+  }
+
+  cur_distortion /= (float) win_cnt;
+
+  if (cur_distortion >= 1.0 && cur_distortion < 1.01) // avoid float accuracy problem at very low QP(e.g.2)
+    cur_distortion = 1.0;
+
+  return cur_distortion;
+}
+
+float compute_luminance_component (imgpel **refImg, imgpel **encImg, int height, int width, int win_height, int win_width, int comp)
+{
+  static const float K1 = 0.01f;
+  static float max_pix_value_sqd;
+  float C1;
+  float win_pixels = (float) (win_width * win_height);
+  float mb_ssim, meanOrg, meanEnc;
+  int imeanOrg, imeanEnc;
+  float cur_distortion = 0.0;
+  int i, j, n, m, win_cnt = 0;
+  int overlapSize = params->SSIMOverlapSize;
+
+  max_pix_value_sqd = (float) (img->max_imgpel_value_comp[comp] * img->max_imgpel_value_comp[comp]);
+  C1 = K1 * K1 * max_pix_value_sqd;
+
+  for (j = 0; j <= height - win_height; j += overlapSize)
+  {
+    for (i = 0; i <= width - win_width; i += overlapSize)
+    {
+      imeanOrg = 0;
+      imeanEnc = 0; 
+      
+      for ( n = j;n < j + win_height;n ++)
+      {
+        for (m = i;m < i + win_width;m ++)
+        {
+          imeanOrg   += refImg[n][m];
+          imeanEnc   += encImg[n][m];
+        }
+      }
+
+      meanOrg = (float) imeanOrg / win_pixels;
+      meanEnc = (float) imeanEnc / win_pixels;
+
+      mb_ssim  = (float) (2.0 * meanOrg * meanEnc + C1);
+      mb_ssim /= (float) (meanOrg * meanOrg + meanEnc * meanEnc + C1);
+
+      cur_distortion += mb_ssim;
+      win_cnt++;
+    }
+  }
+
+  cur_distortion /= (float) win_cnt;
+
+  if (cur_distortion >= 1.0 && cur_distortion < 1.01) // avoid float accuracy problem at very low QP(e.g.2)
+    cur_distortion = 1.0;
+
+  return cur_distortion;
+}
+
+void horizontal_symmetric_extension(int **buffer, int width, int height )
+{
+  int j;
+  int* buf;
+ 
+  int height_plus_pad2 = height + MS_SSIM_PAD2;
+  int width_plus_pad2_minus_one  = width  + MS_SSIM_PAD2 - 1;
+
+  // horizontal PSE
+  for (j = MS_SSIM_PAD2; j < height_plus_pad2; j++ ) {
+    // left column
+    buf = &buffer[j][MS_SSIM_PAD2];
+    buf[-1] = buf[1];
+    buf[-2] = buf[2];
+
+    // right column
+    buf = &buffer[j][width_plus_pad2_minus_one];
+    buf[1] = buf[-1];
+    buf[2] = buf[-2];
+    buf[3] = buf[-3];
+  }
+}
+
+void vertical_symmetric_extension(int **buffer, int width, int height)
+{
+  int i;
+  int* bufminus1;
+  int* bufminus2;
+  int* bufminus3;
+  int* bufplus1;
+  int* bufplus2;
+  int* bufplus3;
+
+  bufminus1 = &buffer[MS_SSIM_PAD2-1][MS_SSIM_PAD2];
+  bufminus2 = &buffer[MS_SSIM_PAD2-2][MS_SSIM_PAD2];
+  bufplus1  = &buffer[MS_SSIM_PAD2+1][MS_SSIM_PAD2];
+  bufplus2  = &buffer[MS_SSIM_PAD2+2][MS_SSIM_PAD2];
+
+  for (i = 0; i < width; i++)
+  {
+    bufminus1[i] = bufplus1[i];
+    bufminus2[i] = bufplus2[i];
+  }
+
+  bufminus1 = &buffer[height + MS_SSIM_PAD2-2][MS_SSIM_PAD2];
+  bufminus2 = &buffer[height + MS_SSIM_PAD2-3][MS_SSIM_PAD2];
+  bufminus3 = &buffer[height + MS_SSIM_PAD2-4][MS_SSIM_PAD2];
+  bufplus1  = &buffer[height + MS_SSIM_PAD2][MS_SSIM_PAD2];
+  bufplus2  = &buffer[height + MS_SSIM_PAD2+1][MS_SSIM_PAD2];
+  bufplus3  = &buffer[height + MS_SSIM_PAD2+2][MS_SSIM_PAD2];
+  for (i = 0; i < width; i++)
+  {
+    bufplus1[i] = bufminus1[i];
+    bufplus2[i] = bufminus2[i];
+    bufplus3[i] = bufminus3[i];
+  }
+}
+
+static void imgpel_to_padded_int(imgpel** src, int **buffer, int width, int height)
+{
+  int i, j;
+  int* tmpDst;
+  imgpel* tmpSrc;
+
+  tmpDst = buffer[MS_SSIM_PAD2];
+  for (j = 0; j < height; j++)
+  {
+    tmpSrc = src[j];
+    tmpDst = &buffer[j + MS_SSIM_PAD2][MS_SSIM_PAD2];
+    for (i = 0; i < width; i++)
+    {
+      tmpDst[i] = (int)tmpSrc[i];
+    }
+  }
+}
+
+void downsample(imgpel** src, imgpel** out, int height, int width)
+{
+  int height2 = height >> 1;
+  int width2  = width  >> 1;
+  int i, j;
+  int ii, jj;
+  int iDst;
+  int tmp, tmp1, tmp2;
+  int* tmpDst;
+  int* tmpSrc;
+  
+  int** itemp;
+  int** dest;
+
+  get_mem2Dint(&itemp, height + MS_SSIM_PAD, width + MS_SSIM_PAD);
+  get_mem2Dint(&dest, height + MS_SSIM_PAD, width2 + MS_SSIM_PAD);
+  
+  imgpel_to_padded_int(src, itemp, width, height);
+  horizontal_symmetric_extension(itemp, width, height);
+
+  for (j = 0; j < height; j++)
+  {
+    tmpDst = dest[j+MS_SSIM_PAD2];
+    tmpSrc = itemp[j+MS_SSIM_PAD2];
+    iDst   = MS_SSIM_PAD2;
+    for (i = 0; i < width2; i++, iDst++)
+    {
+      ii = (i << 1) + MS_SSIM_PAD2;
+      tmp1 = tmpSrc[ii-1] + tmpSrc[ii+2];
+      tmp2 = tmpSrc[ii] + tmpSrc[ii+1];
+      tmpDst[iDst] = tmpSrc[ii-2] + tmpSrc[ii+3] + (tmp1 << 1) + tmp1 + (tmp2 << 5) - (tmp2 << 2);
+      tmpDst[iDst] >>= 6;
+    }
+  }
+ 
+  //Periodic extension
+  vertical_symmetric_extension(dest, width2, height);
+
+  for (i = 0; i < width2; i++) 
+  {
+    ii = i + MS_SSIM_PAD2;
+    for (j = 0; j < height2; j++)
+    {
+      jj = (j << 1) + MS_SSIM_PAD2;
+      tmp1 = dest[jj-1][ii] + dest[jj+2][ii];
+      tmp2 = dest[jj][ii]   + dest[jj+1][ii];
+      tmp = dest[jj-2][ii] + dest[jj+3][ii] + (tmp1 << 1) + tmp1 + (tmp2 << 5) - (tmp2 << 2);
+      out[j][i] = (unsigned char) (tmp >> 6);   //Note: Should change for different bit depths
+    }
+  }
+  free_mem2Dint(itemp);
+  free_mem2Dint(dest);
+}
+
+float compute_ms_ssim(imgpel **refImg, imgpel **encImg, int height, int width, int win_height, int win_width, int comp)
+{
+  float structural[MAX_SSIM_LEVELS];
+  float cur_distortion;
+  float luminance;
+  imgpel** dsRef;
+  imgpel** dsEnc;
+  int m;
+  static int max_ssim_levels_minus_one = MAX_SSIM_LEVELS - 1;
+  static float exponent[5] = {(float)MS_SSIM_BETA0, (float)MS_SSIM_BETA1, (float)MS_SSIM_BETA2, (float)MS_SSIM_BETA3, (float)MS_SSIM_BETA4};
+
+  dsRef = NULL;
+  dsEnc = NULL;
+  get_mem2Dpel(&dsRef, height>>1, width>>1);
+  get_mem2Dpel(&dsEnc, height>>1, width>>1);
+
+  structural[0] = compute_structural_components(refImg, encImg, height, width, win_height, win_width, comp);
+  cur_distortion = (float)pow(structural[0], exponent[0]);
+
+  downsample(refImg, dsRef, height, width);
+  downsample(encImg, dsEnc, height, width);
+
+  for (m = 1; m < MAX_SSIM_LEVELS; m++)
+  {
+    height >>= 1;
+    width >>= 1;
+    structural[m] = compute_structural_components(dsRef, dsEnc, height, width, imin(win_height,height), imin(win_width,width), comp);
+    cur_distortion *= (float)pow(structural[m], exponent[m]);
+    if (m < max_ssim_levels_minus_one)
+    {
+      downsample(dsRef, dsRef, height, width);
+      downsample(dsEnc, dsEnc, height, width);
+    }
+    else
+    {
+      luminance = compute_luminance_component(dsRef, dsEnc, height, width, imin(win_height,height), imin(win_width,width), comp);
+      cur_distortion *= (float)pow(luminance, exponent[m]);
+    }
+  }
+  free_mem2Dpel(dsRef);
+  free_mem2Dpel(dsEnc);
+  dsRef = NULL;
+  dsEnc = NULL;
+
+  return cur_distortion;
+}
+  
+/*!
+ ************************************************************************
+ * \brief
+ *    Find MS-SSIM for all three components
+ ************************************************************************
+ */
+void find_ms_ssim (ImageStructure *ref, ImageStructure *src, DistMetric *metricSSIM)
+{
+  FrameFormat *format = &ref->format;
+
+  metricSSIM->value[0] = compute_ms_ssim (ref->data[0], src->data[0], format->height, format->width, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, 0);
+  // Chroma.
+  if (format->yuv_format != YUV400)
+  {     
+    metricSSIM->value[1]  = compute_ms_ssim (ref->data[1], src->data[1], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 1);
+    metricSSIM->value[2]  = compute_ms_ssim (ref->data[2], src->data[2], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 2);
+  }
+
+  accumulate_average(metricSSIM,  dist->frame_ctr);
+  accumulate_avslice(metricSSIM,  img->type, stats->frame_ctr[img->type]);
+}
diff --git a/lencod/src/img_dist_snr.c b/lencod/src/img_dist_snr.c
new file mode 100644
index 0000000..766ea97
--- /dev/null
+++ b/lencod/src/img_dist_snr.c
@@ -0,0 +1,52 @@
+
+/*!
+ *************************************************************************************
+ * \file img_dist_snr.c
+ *
+ * \brief
+ *    Compute signal to noise ratio (SNR) between the encoded image and the reference image
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *************************************************************************************
+ */
+#include "contributors.h"
+
+#include <math.h>
+
+#include "global.h"
+#include "img_distortion.h"
+#include "enc_statistics.h"
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Find SNR for all three components
+ ************************************************************************
+ */
+void find_snr(ImageStructure *imgREF, ImageStructure *imgSRC, DistMetric *metricSSE, DistMetric *metricPSNR)
+{
+  FrameFormat *format = &imgREF->format;
+  // Luma.
+  metricSSE ->value[0] = (float) compute_SSE(imgREF->data[0], imgSRC->data[0], 0, 0, format->height, format->width);
+  metricPSNR->value[0] = psnr(format->max_value_sq[0], format->size_cmp[0], metricSSE->value[0]);
+
+  // Chroma.
+  if (format->yuv_format != YUV400)
+  {   
+    metricSSE ->value[1] = (float) compute_SSE(imgREF->data[1], imgSRC->data[1], 0, 0, format->height_cr, format->width_cr);
+    metricPSNR->value[1] = psnr(format->max_value_sq[1], format->size_cmp[1], metricSSE->value[1]);
+    metricSSE ->value[2] = (float) compute_SSE(imgREF->data[2], imgSRC->data[2], 0, 0, format->height_cr, format->width_cr);
+    metricPSNR->value[2] = psnr(format->max_value_sq[2], format->size_cmp[2], metricSSE->value[2]);
+  }
+   
+  {
+    accumulate_average(metricSSE,  dist->frame_ctr);
+    accumulate_average(metricPSNR, dist->frame_ctr);
+
+    accumulate_avslice(metricSSE,  img->type, stats->frame_ctr[img->type]);
+    accumulate_avslice(metricPSNR, img->type, stats->frame_ctr[img->type]);
+  }
+}
diff --git a/lencod/src/img_dist_ssim.c b/lencod/src/img_dist_ssim.c
new file mode 100644
index 0000000..b8bbc6f
--- /dev/null
+++ b/lencod/src/img_dist_ssim.c
@@ -0,0 +1,113 @@
+
+/*!
+ *************************************************************************************
+ * \file img_dist_ssim.c
+ *
+ * \brief
+ *    Compute structural similarity (SSIM) index using the encoded image and the reference image
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Zhen Li                         <zli@dolby.com> 
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org>
+ *************************************************************************************
+ */
+#include "contributors.h"
+#include "global.h"
+#include "img_distortion.h"
+#include "enc_statistics.h"
+
+//#define UNBIASED_VARIANCE // unbiased estimation of the variance
+
+float compute_ssim (imgpel **refImg, imgpel **encImg, int height, int width, int win_height, int win_width, int comp)
+{
+  static const float K1 = 0.01f, K2 = 0.03f;
+  static float max_pix_value_sqd;
+  float C1, C2;
+  float win_pixels = (float) (win_width * win_height);
+#ifdef UNBIASED_VARIANCE
+  float win_pixels_bias = win_pixels - 1;
+#else
+  float win_pixels_bias = win_pixels;
+#endif
+  float mb_ssim, meanOrg, meanEnc;
+  float varOrg, varEnc, covOrgEnc;
+  int imeanOrg, imeanEnc, ivarOrg, ivarEnc, icovOrgEnc;
+  float cur_distortion = 0.0;
+  int i, j, n, m, win_cnt = 0;
+  int overlapSize = params->SSIMOverlapSize;
+
+  max_pix_value_sqd = (float) (img->max_imgpel_value_comp[comp] * img->max_imgpel_value_comp[comp]);
+  C1 = K1 * K1 * max_pix_value_sqd;
+  C2 = K2 * K2 * max_pix_value_sqd;
+
+  for (j = 0; j <= height - win_height; j += overlapSize)
+  {
+    for (i = 0; i <= width - win_width; i += overlapSize)
+    {
+      imeanOrg = 0;
+      imeanEnc = 0; 
+      ivarOrg  = 0;
+      ivarEnc  = 0;
+      icovOrgEnc = 0;
+
+      for ( n = j;n < j + win_height;n ++)
+      {
+        for (m = i;m < i + win_width;m ++)
+        {
+          imeanOrg   += refImg[n][m];
+          imeanEnc   += encImg[n][m];
+          ivarOrg    += refImg[n][m] * refImg[n][m];
+          ivarEnc    += encImg[n][m] * encImg[n][m];
+          icovOrgEnc += refImg[n][m] * encImg[n][m];
+        }
+      }
+
+      meanOrg = (float) imeanOrg / win_pixels;
+      meanEnc = (float) imeanEnc / win_pixels;
+
+      varOrg    = ((float) ivarOrg - ((float) imeanOrg) * meanOrg) / win_pixels_bias;
+      varEnc    = ((float) ivarEnc - ((float) imeanEnc) * meanEnc) / win_pixels_bias;
+      covOrgEnc = ((float) icovOrgEnc - ((float) imeanOrg) * meanEnc) / win_pixels_bias;
+
+      mb_ssim  = (float) ((2.0 * meanOrg * meanEnc + C1) * (2.0 * covOrgEnc + C2));
+      mb_ssim /= (float) (meanOrg * meanOrg + meanEnc * meanEnc + C1) * (varOrg + varEnc + C2);
+
+      cur_distortion += mb_ssim;
+      win_cnt++;
+    }
+  }
+
+  cur_distortion /= (float) win_cnt;
+
+  if (cur_distortion >= 1.0 && cur_distortion < 1.01) // avoid float accuracy problem at very low QP(e.g.2)
+    cur_distortion = 1.0;
+
+  return cur_distortion;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Find SSIM for all three components
+ ************************************************************************
+ */
+void find_ssim (ImageStructure *ref, ImageStructure *src, DistMetric *metricSSIM)
+{
+  FrameFormat *format = &ref->format;
+
+  metricSSIM->value[0] = compute_ssim (ref->data[0], src->data[0], format->height, format->width, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, 0);
+  // Chroma.
+  if (format->yuv_format != YUV400)
+  {     
+    metricSSIM->value[1]  = compute_ssim (ref->data[1], src->data[1], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 1);
+    metricSSIM->value[2]  = compute_ssim (ref->data[2], src->data[2], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 2);
+  }
+
+  {
+    accumulate_average(metricSSIM,  dist->frame_ctr);
+    accumulate_avslice(metricSSIM,  img->type, stats->frame_ctr[img->type]);
+  }
+}
+
diff --git a/lencod/src/img_distortion.c b/lencod/src/img_distortion.c
new file mode 100644
index 0000000..5e0db25
--- /dev/null
+++ b/lencod/src/img_distortion.c
@@ -0,0 +1,210 @@
+
+/*!
+ *************************************************************************************
+ * \file img_distortion.c
+ *
+ * \brief
+ *    Compute distortion for encoded image
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *     - Woo-Shik Kim                    <wooshik.kim@usc.edu>
+ *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
+ *************************************************************************************
+ */
+
+#include <math.h>
+#include <time.h>
+#include <sys/timeb.h>
+
+#include "global.h"
+
+#include "refbuf.h"
+#include "mbuffer.h"
+#include "img_luma.h"
+#include "img_chroma.h"
+#include "intrarefresh.h"
+#include "fmo.h"
+#include "sei.h"
+#include "memalloc.h"
+#include "nalu.h"
+#include "ratectl.h"
+#include "mb_access.h"
+#include "output.h"
+#include "cabac.h"
+#include "context_ini.h"
+#include "conformance.h"
+#include "enc_statistics.h"
+
+#include "q_matrix.h"
+#include "q_offsets.h"
+#include "quant4x4.h"
+#include "quant8x8.h"
+#include "wp.h"
+#include "input.h"
+#include "image.h"
+#include "img_distortion.h"
+#include "img_dist_snr.h"
+#include "img_dist_ssim.h"
+#include "img_dist_ms_ssim.h"
+#include "cconv_yuv2rgb.h"
+
+// images for distortion calculation
+ImageStructure imgSRC, imgREF;
+extern ImageStructure imgRGB_src, imgRGB_ref;
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Metric accumulator
+ ************************************************************************
+ */
+void accumulate_metric(float *ave_metric, float cur_metric, int frames)
+{
+  *ave_metric = (float) (*ave_metric * (frames - 1) + cur_metric) / frames;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Accumulate distortion for all components
+ ************************************************************************
+ */
+void accumulate_average(DistMetric *metric, int frames)
+{
+  accumulate_metric(&metric->average[0],  metric->value[0],  frames);
+  accumulate_metric(&metric->average[1],  metric->value[1],  frames);
+  accumulate_metric(&metric->average[2],  metric->value[2],  frames);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Accumulate distortion for all components for slice_type
+ ************************************************************************
+ */
+void accumulate_avslice(DistMetric *metric, int slice_type, int frames)
+{
+  accumulate_metric(&metric->avslice[slice_type][0], metric->value[0],  frames);
+  accumulate_metric(&metric->avslice[slice_type][1], metric->value[1],  frames);
+  accumulate_metric(&metric->avslice[slice_type][2], metric->value[2],  frames);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Find distortion for all three components
+ ************************************************************************
+ */
+void find_distortion (void)
+{
+  int64 diff_cmp[3] = {0};
+
+  //  Calculate SSE for Y, U and V.
+  if (img->structure!=FRAME)
+  {
+    // Luma.
+    diff_cmp[0] += compute_SSE(pCurImg, imgY_com, 0, 0, params->output.height, params->output.width);
+
+    // Chroma.
+    if (img->yuv_format != YUV400)
+    {
+      diff_cmp[1] += compute_SSE(pImgOrg[1], imgUV_com[0], 0, 0, params->output.height_cr, params->output.width_cr);
+      diff_cmp[2] += compute_SSE(pImgOrg[2], imgUV_com[1], 0, 0, params->output.height_cr, params->output.width_cr);
+    }
+  }
+  else
+  {
+    if( IS_INDEPENDENT(params) )
+    {
+      enc_picture = enc_frame_picture[0];     
+    }
+    pCurImg   = img_org_frm[0];
+    pImgOrg[0] = img_org_frm[0];
+
+    // Luma.
+    diff_cmp[0] += compute_SSE(pImgOrg[0], enc_picture->imgY, 0, 0, params->output.height, params->output.width);
+
+    // Chroma.
+    if (img->yuv_format != YUV400)
+    {
+      pImgOrg[1] = img_org_frm[1];
+      pImgOrg[2] = img_org_frm[2]; 
+
+      diff_cmp[1] += compute_SSE(pImgOrg[1], enc_picture->imgUV[0], 0, 0, params->output.height_cr, params->output.width_cr);
+      diff_cmp[2] += compute_SSE(pImgOrg[2], enc_picture->imgUV[1], 0, 0, params->output.height_cr, params->output.width_cr);
+    }
+  }
+
+  // This should be assigned to the SSE structure. Should double check code.
+  dist->metric[SSE].value[0] = (float) diff_cmp[0];
+  dist->metric[SSE].value[1] = (float) diff_cmp[1];
+  dist->metric[SSE].value[2] = (float) diff_cmp[2];
+}
+
+void select_img(ImageStructure *imgSRC, ImageStructure *imgREF)
+{
+  if (img->fld_flag != 0)
+  {
+    imgSRC->format = params->output;
+    imgREF->format = params->output;
+
+    imgREF->data[0] = pCurImg;
+    imgSRC->data[0] = imgY_com;
+
+    if (img->yuv_format != YUV400)
+    {
+      imgREF->data[1] = pImgOrg[1];
+      imgREF->data[2] = pImgOrg[2];
+      imgSRC->data[1] = imgUV_com[0];
+      imgSRC->data[2] = imgUV_com[1];
+    }
+  }
+  else
+  {
+    imgSRC->format = params->output;
+    imgREF->format = params->output;
+
+    imgREF->data[0] = img_org_frm[0];
+
+    if ((params->PicInterlace == ADAPTIVE_CODING) || IS_INDEPENDENT(params))
+    {
+      enc_picture = enc_frame_picture[0];
+    }
+    imgSRC->data[0] = enc_picture->imgY;
+
+    if (img->yuv_format != YUV400)
+    {
+      imgREF->data[1] = img_org_frm[1];
+      imgREF->data[2] = img_org_frm[2];
+
+      imgSRC->data[1] = enc_picture->imgUV[0];
+      imgSRC->data[2] = enc_picture->imgUV[1];
+    }
+  }
+}
+
+void compute_distortion(void)
+{
+  if (params->Verbose != 0)
+  {
+    select_img(&imgSRC, &imgREF);
+
+    find_snr (&imgREF, &imgSRC, &dist->metric[SSE], &dist->metric[PSNR]);
+    if (params->Distortion[SSIM] == 1)
+      find_ssim (&imgREF, &imgSRC, &dist->metric[SSIM]);
+    if (params->Distortion[MS_SSIM] == 1)
+      find_ms_ssim(&imgREF, &imgSRC, &dist->metric[MS_SSIM]);
+    // RGB Distortion
+    if(params->DistortionYUVtoRGB == 1)
+    {
+      YUVtoRGB(&imgREF, &imgRGB_ref);
+      YUVtoRGB(&imgSRC, &imgRGB_src);
+      find_snr (&imgRGB_ref, &imgRGB_src, &dist->metric[SSE_RGB], &dist->metric[PSNR_RGB]);
+      if (params->Distortion[SSIM] == 1)
+        find_ssim (&imgRGB_ref, &imgRGB_src, &dist->metric[SSIM_RGB]);
+      if (params->Distortion[MS_SSIM] == 1)
+        find_ms_ssim(&imgRGB_ref, &imgRGB_src, &dist->metric[MS_SSIM_RGB]);
+    }
+  }
+}
diff --git a/lencod/src/input.c b/lencod/src/input.c
index a1ee97b..345fa0a 100644
--- a/lencod/src/input.c
+++ b/lencod/src/input.c
@@ -21,6 +21,7 @@
 
 #include "global.h"
 #include "input.h"
+#include "report.h"
 
 unsigned char *buf;
  
@@ -501,7 +502,7 @@ void ReadOneFrame (int FrameNoInFile, int HeaderSize, FrameFormat *source, Frame
 
     if (read(p_in, buf, (int) framesize_in_bytes) != (int) framesize_in_bytes)
     {
-      printf ("ReadOneFrame: cannot read %d bytes from input file, unexpected EOF?, exiting", (int) framesize_in_bytes);
+      printf ("ReadOneFrame: cannot read %d bytes from input file, unexpected EOF, exiting...\n", (int) framesize_in_bytes);
       report_stats_on_error();
     }
 
diff --git a/lencod/src/lencod.c b/lencod/src/lencod.c
index 90db6c4..d27f81d 100644
--- a/lencod/src/lencod.c
+++ b/lencod/src/lencod.c
@@ -14,7 +14,7 @@
  *     The main contributors are listed in contributors.h
  *
  *  \version
- *     JM 14.0 (FRExt)
+ *     JM 14.1 (FRExt)
  *
  *  \note
  *     tags are used for document system "doxygen"
@@ -49,40 +49,33 @@
 #include <sys/timeb.h>
 #include "global.h"
 
+#include "cconv_yuv2rgb.h"
 #include "configfile.h"
-#include "leaky_bucket.h"
-#include "memalloc.h"
-#include "intrarefresh.h"
-#include "fmo.h"
-#include "sei.h"
-#include "parset.h"
+#include "context_ini.h"
+#include "explicit_gop.h"
+#include "filehandle.h"
 #include "image.h"
 #include "input.h"
-#include "output.h"
-
+#include "intrarefresh.h"
+#include "leaky_bucket.h"
+#include "memalloc.h"
 #include "me_epzs.h"
 #include "me_umhex.h"
 #include "me_umhexsmp.h"
-
-#include "ratectl.h"
-#include "explicit_gop.h"
-#include "context_ini.h"
-
+#include "output.h"
+#include "parset.h"
 #include "q_matrix.h"
 #include "q_offsets.h"
+#include "ratectl.h"
+#include "report.h"
 #include "rdo_quant.h"
+#include "errdo.h"
+#include "rdopt.h"
+#include "wp_mcprec.h"
 
-#define JM      "14 (FRExt)"
-#define VERSION "14.0"
-#define EXT_VERSION "(FRExt)"
-
-InputParameters inputs,      *params = &inputs;
-ImageParameters images,      *img   = &images;
-StatParameters  statistics,  *stats = &statistics;
-SNRParameters   snrs,        *snr   = &snrs;
-Decoders decoders, *decs=&decoders;
-
-static void information_init(void);
+InputParameters  inputs, *params = &inputs;
+ImageParameters  images, *img    = &images;
+Decoders       decoders, *decs   = &decoders;
 
 #ifdef _ADAPT_LAST_GROUP_
 int initial_Bframes = 0;
@@ -98,36 +91,33 @@ extern ColocatedParams *Co_located;
 extern ColocatedParams *Co_located_JV[MAX_PLANE];  //!< Co_located to be used during 4:4:4 independent mode encoding
 extern double *mb16x16_cost_frame;
 extern int FrameNumberInFile;
-static char DistortionType[3][20] = {"SAD", "SSE", "Hadamard SAD"};
 
-void Init_Motion_Search_Module (void);
-void Clear_Motion_Search_Module (void);
-void report_frame_statistic(void);
+extern ImageStructure imgRGB_src, imgRGB_ref; // RGB Distortion Metric
+
+
+extern void Init_Motion_Search_Module (void);
+extern void Clear_Motion_Search_Module (void);
+
+static void SetImgType(void);
 void SetLevelIndices(void);
 void chroma_mc_setup(void);
-
-void init_stats (void)
+int  get_mem_mv  (short*******);
+int  get_mem_bipred_mv (short********);
+void free_mem_bipred_mv (short*******);
+void free_mem_mv (short******);
+static void init_img( ImageParameters *img, InputParameters *params);
+static void init_poc(void);
+
+void init_stats (StatParameters *stats, DistortionParams *dist)
 {
   stats->successive_Bframe = params->successive_Bframe;
-  stats->bit_ctr_I = 0;
-  stats->bit_ctr_P = 0;
-  stats->bit_ctr_B = 0;
-  snr->snr_y = 0.0;
-  snr->snr_u = 0.0;
-  snr->snr_v = 0.0;
-  snr->snr_y1 = 0.0;
-  snr->snr_u1 = 0.0;
-  snr->snr_v1 = 0.0;
-  snr->snr_ya = 0.0;
-  snr->snr_ua = 0.0;
-  snr->snr_va = 0.0;
-  snr->sse_y  = 0.0;
-  snr->sse_u  = 0.0;
-  snr->sse_v  = 0.0;
-  snr->msse_y = 0.0;
-  snr->msse_u = 0.0;
-  snr->msse_v = 0.0;
-  snr->frame_ctr = 0;
+  stats->frame_counter = 0;  
+  memset(stats->frame_ctr,   0, NUM_SLICE_TYPES * sizeof(int));
+  memset(stats->bit_counter, 0, NUM_SLICE_TYPES * sizeof(int64));
+
+  // Distortion
+  dist->frame_ctr = 0;
+  memset(dist->metric, 0, TOTAL_DIST_TYPES * sizeof(DistMetric));
 }
 
 /*!
@@ -144,6 +134,7 @@ void init_frame_params()
   {
     if (!params->adaptive_idr_period && ( img->frm_number - img->lastIDRnumber ) % params->idr_period == 0 )
       img->nal_reference_idc = NALU_PRIORITY_HIGHEST;
+
     if (params->adaptive_idr_period == 1 && ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period == 0 )
       img->nal_reference_idc = NALU_PRIORITY_HIGHEST;
     else
@@ -205,13 +196,12 @@ void init_frame_params()
  */
 int main(int argc,char **argv)
 {
-  int nplane;
   int primary_disp = 0;
   giRDOpt_B8OnlyFlag = 0;
 
   p_dec = p_in = -1;
 
-  p_stat = p_log = p_trace = NULL;
+  p_log = p_trace = NULL;
 
   frame_statistic_start = 1;
 
@@ -226,9 +216,15 @@ int main(int argc,char **argv)
   GenerateParameterSets();
   SetLevelIndices();
 
-  init_img();
+  init_img(img, params);
+
+  init_rdopt(params);
+
+  if (params->rdopt == 3)
+  {
+    init_error_conceal(params->ErrorConcealment); 
+  }
 
-  init_rdopt ();
 #ifdef _LEAKYBUCKET_
   Bit_Buffer = malloc((params->no_frames * (params->successive_Bframe + 1) + 1) * sizeof(long));
 #endif
@@ -247,28 +243,30 @@ int main(int argc,char **argv)
   dpb.init_done = 0;
   init_dpb();
   init_out_buffer();
-  init_stats();
+  init_stats(stats, dist);
 
   enc_picture = NULL;
 
   init_global_buffers();
 
+  if ( params->WPMCPrecision )
+  {
+    wpxInitWPXPasses(params);
+  }
+
   create_context_memory ();
   Init_Motion_Search_Module ();
-  information_init();
+  information_init(img, params, stats);
+
+  if(params->DistortionYUVtoRGB)
+    init_YUVtoRGB();
 
   //Rate control
   if (params->RCEnable)
     rc_init_sequence();
 
-  if (params->SearchMode == UM_HEX)
-    UMHEX_DefineThreshold();
-
-  // Init frame type counter. Only supports single slice per frame.
-  memset(frame_ctr, 0, 5 * sizeof(int));
-
   img->last_valid_reference = 0;
-  tot_time=0;                 // time for total encoding session
+  tot_time = 0;                 // time for total encoding session
 
 #ifdef _ADAPT_LAST_GROUP_
   if (params->last_frame > 0)
@@ -284,7 +282,6 @@ int main(int argc,char **argv)
   stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
   start_frame_no_in_this_IGOP = 0;
 
-
   if (params->UseRDOQuant)
     precalculate_unary_exp_golomb_level();
 
@@ -316,9 +313,9 @@ int main(int argc,char **argv)
     }
 
 #ifdef _ADAPT_LAST_GROUP_
-    if (params->successive_Bframe && params->last_frame && IMG_NUMBER+1 == params->no_frames)
+    if (params->successive_Bframe && params->last_frame && (IMG_NUMBER + 1) == params->no_frames)
     {
-      int bi = (int)((float)(params->jumpd+1)/(params->successive_Bframe + 1.0) + 0.499999);
+      int bi = (int)((float)(params->jumpd + 1)/(params->successive_Bframe + 1.0) + 0.499999);
 
       params->successive_Bframe = ((params->last_frame - (img->frm_number - 1)*(params->jumpd + 1)) / bi) - 1;
 
@@ -363,16 +360,11 @@ int main(int argc,char **argv)
     if (img->nal_reference_idc == 0)
     {
       primary_disp ++;
-      //img->frame_num -= 1;
-      //img->frame_num %= max_frame_num;
     }
 
     if (img->currentPicture->idr_flag)
     {
       img->idr_gop_number = 0;
-      //start_frame_no_in_this_IGOP = img->frm_number;
-      //start_tr_in_this_IGOP = img->toppoc;
-      // start_tr_in_this_IGOP = (img->frm_number - 1 ) * (params->jumpd + 1) +1;
     }
     else
       img->idr_gop_number ++;
@@ -380,74 +372,15 @@ int main(int argc,char **argv)
     encode_enhancement_layer();    
   }
   // terminate sequence
-  terminate_sequence();
-
-  flush_dpb();
-
-  close(p_in);
-  if (-1 != p_dec)
-    close(p_dec);
-  if (p_trace)
-    fclose(p_trace);
-
-  Clear_Motion_Search_Module ();
-
-  RandomIntraUninit();
-  FmoUninit();
-
-  if (params->HierarchicalCoding)
-    clear_gop_structure ();
-
-  // free structure for rd-opt. mode decision
-  clear_rdopt ();
-
-#ifdef _LEAKYBUCKET_
-  calc_buffer();
-#endif
-
-  // report everything
-  report();
-
-#ifdef _LEAKYBUCKET_
-  if (Bit_Buffer)
-  free(Bit_Buffer);
-#endif
-
-  free_dpb();
-  if( IS_INDEPENDENT(params) )
-  {
-    for( nplane=0; nplane<MAX_PLANE; nplane++ )
-    {
-      free_colocated(Co_located_JV[nplane]);
-    }
-  }
-  else
-  {
-    free_colocated(Co_located);
-  }
-  uninit_out_buffer();
-
-  free_global_buffers();
-
-  // free image mem
-  free_img ();
-  free_context_memory ();
-  FreeNalPayloadBuffer();
-  FreeParameterSets();
+  free_encoder_memory(img);
 
   return 0;
 }
-/*!
- ***********************************************************************
- * \brief
- *    Terminates and reports statistics on error.
- *
- ***********************************************************************
- */
-void report_stats_on_error(void)
+
+
+void free_encoder_memory(ImageParameters *img)
 {
   int nplane;
-  params->no_frames = img->frm_number;
   terminate_sequence();
 
   flush_dpb();
@@ -455,7 +388,6 @@ void report_stats_on_error(void)
   close(p_in);
   if (-1 != p_dec)
     close(p_dec);
-
   if (p_trace)
     fclose(p_trace);
 
@@ -468,19 +400,22 @@ void report_stats_on_error(void)
     clear_gop_structure ();
 
   // free structure for rd-opt. mode decision
-  clear_rdopt ();
+  clear_rdopt (params);
 
 #ifdef _LEAKYBUCKET_
   calc_buffer();
 #endif
 
-  if (params->ReportFrameStats)
-    report_frame_statistic();
-
   // report everything
-  report();
+  report(img, params, stats);
+
+#ifdef _LEAKYBUCKET_
+  if (Bit_Buffer)
+    free(Bit_Buffer);
+#endif
 
   free_dpb();
+
   if( IS_INDEPENDENT(params) )
   {
     for( nplane=0; nplane<MAX_PLANE; nplane++ )
@@ -492,6 +427,7 @@ void report_stats_on_error(void)
   {
     free_colocated(Co_located);
   }
+
   uninit_out_buffer();
 
   free_global_buffers();
@@ -501,7 +437,6 @@ void report_stats_on_error(void)
   free_context_memory ();
   FreeNalPayloadBuffer();
   FreeParameterSets();
-  exit (-1);
 }
 
 /*!
@@ -523,27 +458,24 @@ void init_poc()
 
   if (params->BRefPictures == 1)
   {
-    img->offset_for_non_ref_pic  =   0;
-    img->offset_for_ref_frame[0] =   2;
+    img->offset_for_non_ref_pic  =  0;
+    img->offset_for_ref_frame[0] =  2;
   }
   else
   {
-    img->offset_for_non_ref_pic  =  -2*(params->successive_Bframe);
-    img->offset_for_ref_frame[0] =   2*(params->successive_Bframe+1);
+    img->offset_for_non_ref_pic  = -2*(params->successive_Bframe);
+    img->offset_for_ref_frame[0] =  2*(params->successive_Bframe + 1);
   }
 
-  if ((params->PicInterlace==FRAME_CODING) && (params->MbInterlace==FRAME_CODING))
-    img->offset_for_top_to_bottom_field=0;
-  else
-    img->offset_for_top_to_bottom_field=1;
-
   if ((params->PicInterlace==FRAME_CODING) && (params->MbInterlace==FRAME_CODING))
   {
+    img->offset_for_top_to_bottom_field = 0;
     img->pic_order_present_flag = FALSE;
     img->delta_pic_order_cnt_bottom = 0;
   }
   else
   {
+    img->offset_for_top_to_bottom_field = 1;
     img->pic_order_present_flag = TRUE;
     img->delta_pic_order_cnt_bottom = 1;
   }
@@ -583,7 +515,7 @@ void CAVLC_init(void)
  *    Image Parameters ImageParameters *img
  ***********************************************************************
  */
-void init_img()
+static void init_img( ImageParameters *img, InputParameters *params)
 {
   int i, j;
   int byte_abs_range;
@@ -602,10 +534,10 @@ void init_img()
   img->bitdepth_luma_qp_scale   = 3 *  img->bitdepth_lambda_scale;
   img->dc_pred_value_comp[0]    =  1<<(img->bitdepth_luma - 1);
   img->max_imgpel_value_comp[0] = (1<<img->bitdepth_luma) - 1;
+  img->max_imgpel_value_comp_sq[0] = img->max_imgpel_value_comp[0] * img->max_imgpel_value_comp[0];
 
-  img->dc_pred_value            =  img->dc_pred_value_comp[0]; // set defaults
+  img->dc_pred_value            = img->dc_pred_value_comp[0]; // set defaults
   img->max_imgpel_value         = img->max_imgpel_value_comp[0];
-
   img->mb_size[0][0]            = img->mb_size[0][1] = MB_BLOCK_SIZE;
 
   // Initialization for RC QP parameters (could be placed in ratectl.c)
@@ -613,8 +545,8 @@ void init_img()
   img->RCMaxQP                = params->RCMaxQP[P_SLICE];
 
   // Set current residue & prediction array pointers
-  img->curr_res = img->m7[0];
-  img->curr_prd = img->mpr[0];
+  img->curr_res = img->mb_rres[0];
+  img->curr_prd = img->mb_pred[0];
 
   if (img->yuv_format != YUV400)
   {
@@ -624,8 +556,11 @@ void init_img()
     img->dc_pred_value_comp[2]    = img->dc_pred_value_comp[1];
     img->max_imgpel_value_comp[1] = (1<<img->bitdepth_chroma) - 1;
     img->max_imgpel_value_comp[2] = img->max_imgpel_value_comp[1];
+    img->max_imgpel_value_comp_sq[1] = img->max_imgpel_value_comp[1] * img->max_imgpel_value_comp[1];
+    img->max_imgpel_value_comp_sq[2] = img->max_imgpel_value_comp[2] * img->max_imgpel_value_comp[2];
     img->num_blk8x8_uv            = (1<<img->yuv_format)&(~(0x1));
     img->num_cdc_coeff            = img->num_blk8x8_uv << 1;
+
     img->mb_size[1][0] = img->mb_size[2][0] = img->mb_cr_size_x = (img->yuv_format == YUV420 || img->yuv_format == YUV422) ? 8 : 16;
     img->mb_size[1][1] = img->mb_size[2][1] = img->mb_cr_size_y = (img->yuv_format == YUV444 || img->yuv_format == YUV422) ? 16 : 8;
 
@@ -640,6 +575,8 @@ void init_img()
     img->bitdepth_scale[1]   = 0;
     img->max_imgpel_value_comp[1] = 0;
     img->max_imgpel_value_comp[2] = img->max_imgpel_value_comp[1];
+    img->max_imgpel_value_comp_sq[1] = img->max_imgpel_value_comp[1] * img->max_imgpel_value_comp[1];
+    img->max_imgpel_value_comp_sq[2] = img->max_imgpel_value_comp[2] * img->max_imgpel_value_comp[2];
     img->num_blk8x8_uv       = 0;
     img->num_cdc_coeff       = 0;
     img->mb_size[1][0] = img->mb_size[2][0] = img->mb_cr_size_x = 0;
@@ -651,7 +588,7 @@ void init_img()
     img->chroma_qp_offset[0] = 0;
     img->chroma_qp_offset[1] = 0;
   }  
- 
+
   //img->pic_unit_size_on_disk = (imax(img->bitdepth_luma , img->bitdepth_chroma) > 8) ? 16 : 8;
   img->pic_unit_size_on_disk = (imax(params->source.bit_depth[0], params->source.bit_depth[1]) > 8) ? 16 : 8;
   img->out_unit_size_on_disk = (imax(params->output.bit_depth[0], params->output.bit_depth[1]) > 8) ? 16 : 8;
@@ -688,8 +625,7 @@ void init_img()
 
     if (params->BiPredMotionEstimation)
     {
-      get_mem_mv (&(img->bipred_mv1));
-      get_mem_mv (&(img->bipred_mv2));
+      get_mem_bipred_mv(&(img->bipred_mv)); 
     }
   }
 
@@ -751,7 +687,7 @@ void init_img()
 
     get_mem_ACcoeff (&(rddata_trellis_best.cofAC));
     get_mem_DCcoeff (&(rddata_trellis_best.cofDC));
-    
+
     if (!params->IntraProfile)
     {          
       get_mem_mv (&(rddata_trellis_curr.pred_mv));
@@ -768,7 +704,7 @@ void init_img()
     }
   }
 
-  byte_abs_range = (imax(img->max_imgpel_value_comp[0],img->max_imgpel_value_comp[1]) + 1) * 2;
+  byte_abs_range = (imax(img->max_imgpel_value_comp[0], img->max_imgpel_value_comp[1]) + 1) * 2;
 
   if ((img->quad = (int*)calloc (byte_abs_range, sizeof(int))) == NULL)
     no_mem_exit ("init_img: img->quad");
@@ -788,7 +724,7 @@ void init_img()
 
   if (img->yuv_format != YUV400)
   {
-    img->width_cr = img->width  * mb_width_cr[img->yuv_format]  / 16;
+    img->width_cr = img->width  * mb_width_cr [img->yuv_format] / 16;
     img->height_cr= img->height * mb_height_cr[img->yuv_format] / 16;
   }
   else
@@ -796,20 +732,24 @@ void init_img()
     img->width_cr = 0;
     img->height_cr= 0;
   }
+
   img->height_cr_frame = img->height_cr;
 
   img->size = img->width * img->height;
   img->size_cr = img->width_cr * img->height_cr;
 
-  img->PicWidthInMbs    = img->width/MB_BLOCK_SIZE;
-  img->FrameHeightInMbs = img->height/MB_BLOCK_SIZE;
+  img->PicWidthInMbs    = img->width  / MB_BLOCK_SIZE;
+  img->FrameHeightInMbs = img->height / MB_BLOCK_SIZE;
   img->FrameSizeInMbs   = img->PicWidthInMbs * img->FrameHeightInMbs;
 
   img->PicHeightInMapUnits = ( active_sps->frame_mbs_only_flag ? img->FrameHeightInMbs : img->FrameHeightInMbs/2 );
+  
+  if ((img->b8x8info = (Block8x8Info *) calloc(1, sizeof(Block8x8Info))) == NULL)
+     no_mem_exit("init_img: img->block8x8info");
 
   if( IS_INDEPENDENT(params) )
   {
-    for( i=0; i<MAX_PLANE; i++ ){
+    for( i = 0; i < MAX_PLANE; i++ ){
       if ((img->mb_data_JV[i] = (Macroblock *) calloc(img->FrameSizeInMbs,sizeof(Macroblock))) == NULL)
         no_mem_exit("init_img: img->mb_data_JV");
     }
@@ -836,7 +776,7 @@ void init_img()
   }
   get_mem2D((byte***)&(img->ipredmode), img->height_blk, img->width_blk);        //need two extra rows at right and bottom
   get_mem2D((byte***)&(img->ipredmode8x8), img->height_blk, img->width_blk);     // help storage for ipredmode 8x8, inserted by YV
-  memset(&(img->ipredmode[0][0]), -1, img->height_blk * img->width_blk *sizeof(char));
+  memset(&(img->ipredmode[0][0])   , -1, img->height_blk * img->width_blk *sizeof(char));
   memset(&(img->ipredmode8x8[0][0]), -1, img->height_blk * img->width_blk *sizeof(char));
 
   get_mem2D((byte***)&(rddata_top_frame_mb.ipredmode), img->height_blk, img->width_blk);
@@ -849,34 +789,35 @@ void init_img()
     get_mem2D((byte***)&(rddata_top_field_mb.ipredmode), img->height_blk, img->width_blk);
     get_mem2D((byte***)&(rddata_bot_field_mb.ipredmode), img->height_blk, img->width_blk);
   }
+
   // CAVLC mem
   get_mem3Dint(&(img->nz_coeff), img->FrameSizeInMbs, 4, 4+img->num_blk8x8_uv);
-
-
-  get_mem2Ddb_offset(&(img->lambda_md), 10, 52 + img->bitdepth_luma_qp_scale,img->bitdepth_luma_qp_scale);
-  get_mem3Ddb_offset (&(img->lambda_me), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
-  get_mem3Dint_offset(&(img->lambda_mf), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
+  CAVLC_init();
+  
+  get_mem2Dolm     (&(img->lambda), 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
+  get_mem2Dodouble (&(img->lambda_md), 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
+  get_mem3Dodouble (&(img->lambda_me), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
+  get_mem3Doint    (&(img->lambda_mf), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
 
   if (params->CtxAdptLagrangeMult == 1)
   {
-    get_mem2Ddb_offset(&(img->lambda_mf_factor), 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
+    get_mem2Dodouble(&(img->lambda_mf_factor), 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
   }
 
-  CAVLC_init();
-
   img->b_frame_to_code = 0;
   img->GopLevels = (params->successive_Bframe) ? 1 : 0;
   img->mb_y_upd=0;
 
   RandomIntraInit (img->PicWidthInMbs, img->FrameHeightInMbs, params->RandomIntraMBRefresh);
 
-  InitSEIMessages();  // Tian Dong (Sept 2002)
+  InitSEIMessages(); 
 
   initInput(&params->source, &params->output);
 
   // Allocate I/O Frame memory
   if (AllocateFrameMemory(img, params->source.size))
     no_mem_exit("AllocateFrameMemory: buf");
+
   // Initialize filtering parameters. If sending parameters, the offsets are
   // multiplied by 2 since inputs are taken in "div 2" format.
   // If not sending parameters, all fields are cleared
@@ -884,7 +825,7 @@ void init_img()
   {
     for (j = 0; j < 2; j++)
     {
-      for (i = 0; i < 5; i++)
+      for (i = 0; i < NUM_SLICE_TYPES; i++)
       {
         params->DFAlpha[j][i] <<= 1;
         params->DFBeta [j][i] <<= 1;
@@ -895,23 +836,16 @@ void init_img()
   {
     for (j = 0; j < 2; j++)
     {
-      for (i = 0; i < 5; i++)
+      for (i = 0; i < NUM_SLICE_TYPES; i++)
       {
         params->DFDisableIdc[j][i] = 0;
-        params->DFAlpha[j][i] = 0;
-        params->DFBeta[j][i] = 0;
+        params->DFAlpha     [j][i] = 0;
+        params->DFBeta      [j][i] = 0;
       }
     }
   }
 
-  if( params->separate_colour_plane_flag )
-  {
-    img->ChromaArrayType = 0;
-  }
-  else
-  {
-    img->ChromaArrayType = params->yuv_format;
-  }
+  img->ChromaArrayType = params->separate_colour_plane_flag ? 0 : params->yuv_format;
 
   if (params->RDPictureDecision)
   {
@@ -943,8 +877,7 @@ void free_img ()
 
     if (params->BiPredMotionEstimation)
     {
-      free_mem_mv (img->bipred_mv1);
-      free_mem_mv (img->bipred_mv2);
+      free_mem_bipred_mv (img->bipred_mv);
     }
   }
 
@@ -1027,9 +960,9 @@ void free_img ()
 
   if (params->MbInterlace)
   {
-    free_mem2D((byte**)rddata_bot_frame_mb.ipredmode);
-    free_mem2D((byte**)rddata_top_field_mb.ipredmode);
-    free_mem2D((byte**)rddata_bot_field_mb.ipredmode);
+    free_mem2D((byte**) rddata_bot_frame_mb.ipredmode);
+    free_mem2D((byte**) rddata_top_field_mb.ipredmode);
+    free_mem2D((byte**) rddata_bot_field_mb.ipredmode);
   }
 }
 
@@ -1072,956 +1005,6 @@ void free_picture(Picture *pic)
 }
 
 
-/*!
- ************************************************************************
- * \brief
- *    Reports frame statistical data to a stats file
- ************************************************************************
- */
-void report_frame_statistic()
-{
-  FILE *p_stat_frm = NULL;
-  static int64 last_mode_use[NUM_PIC_TYPE][MAXMODE];
-  static int   last_b8_mode_0[NUM_PIC_TYPE][2];
-  static int   last_mode_chroma_use[4];
-  static int64 last_bit_ctr_n = 0;
-  int i;
-  char name[30];
-  int bitcounter;
-
-#ifndef WIN32
-  time_t now;
-  struct tm *l_time;
-  char string[1000];
-#else
-  char timebuf[128];
-#endif
-
-
-  // write to log file
-  if ((p_stat_frm = fopen("stat_frame.dat", "r")) == 0)            // check if file exists
-  {
-    if ((p_stat_frm = fopen("stat_frame.dat", "a")) == NULL)       // append new statistic at the end
-    {
-      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
-      error(errortext, 500);
-    }
-    else                                            // Create header for new log file
-    {
-      fprintf(p_stat_frm, " --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
-      fprintf(p_stat_frm, "|            Encoder statistics. This file is generated during first encoding session, new sessions will be appended                                                                                                                                                                                                                                                                                                                                                              |\n");
-      fprintf(p_stat_frm, " --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
-    }
-  }
-  else
-  {
-    fclose (p_stat_frm);
-    if ((p_stat_frm = fopen("stat_frame.dat", "a")) == NULL)       // File exists, just open for appending
-    {
-      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
-      error(errortext, 500);
-    }
-  }
-
-  if (frame_statistic_start)
-  {
-    fprintf(p_stat_frm, "|     ver     | Date  | Time  |    Sequence                  |Frm | QP |P/MbInt|   Bits   |  SNRY  |  SNRU  |  SNRV  |  I4  |  I8  | I16  | IC0  | IC1  | IC2  | IC3  | PI4  | PI8  | PI16 |  P0  |  P1  |  P2  |  P3  | P1*8*| P1*4*| P2*8*| P2*4*| P3*8*| P3*4*|  P8  | P8:4 | P4*8*| P4*4*| P8:5 | P8:6 | P8:7 | BI4  | BI8  | BI16 |  B0  |  B1  |  B2  |  B3  | B0*8*| B0*4*| B1*8*| B1*4*| B2*8*| B2*4*| B3*8*| B3*4*|  B8  | B8:0 |B80*8*|B80*4*| B8:4 | B4*8*| B4*4*| B8:5 | B8:6 | B8:7 |\n");
-    fprintf(p_stat_frm, " ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
-  }
-
-  //report
-  fprintf(p_stat_frm, "|%4s/%s", VERSION, EXT_VERSION);
-
-#ifdef WIN32
-  _strdate( timebuf );
-  fprintf(p_stat_frm, "| %1.5s |", timebuf);
-
-  _strtime( timebuf);
-  fprintf(p_stat_frm, " % 1.5s |", timebuf);
-#else
-  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
-  time (&now);
-  l_time = localtime (&now);
-  strftime (string, sizeof string, "%d-%b-%Y", l_time);
-  fprintf(p_stat_frm, "| %1.5s |", string );
-
-  strftime (string, sizeof string, "%H:%M:%S", l_time);
-  fprintf(p_stat_frm, " %1.5s |", string);
-#endif
-
-  for (i=0;i<30;i++)
-    name[i]=params->infile[i + imax(0,(int) (strlen(params->infile)- 30))]; // write last part of path, max 30 chars
-
-  fprintf(p_stat_frm, "%30.30s|", name);
-
-  fprintf(p_stat_frm, "%3d |", frame_no);
-
-  fprintf(p_stat_frm, "%3d |", img->qp);
-
-  fprintf(p_stat_frm, "  %d/%d  |", params->PicInterlace, params->MbInterlace);
-
-
-  if (img->frm_number == 0 && img->frame_num == 0)
-  {
-    bitcounter = (int) stats->bit_ctr_I;
-  }
-  else
-  {
-    bitcounter = (int) (stats->bit_ctr_n - last_bit_ctr_n);
-    last_bit_ctr_n = stats->bit_ctr_n;
-  }
-
-  //report bitrate
-  fprintf(p_stat_frm, " %9d|", bitcounter);
-
-  //report snr's
-  fprintf(p_stat_frm, " %2.4f| %2.4f| %2.4f|", snr->snr_y, snr->snr_u, snr->snr_v);
-
-  //report modes
-  //I-Modes
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I4MB] - last_mode_use[I_SLICE][I4MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I8MB] - last_mode_use[I_SLICE][I8MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I16MB] - last_mode_use[I_SLICE][I16MB]);
-
-  //chroma intra mode
-  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[0] - last_mode_chroma_use[0]);
-  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[1] - last_mode_chroma_use[1]);
-  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[2] - last_mode_chroma_use[2]);
-  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[3] - last_mode_chroma_use[3]);
-
-  //P-Modes
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I4MB] - last_mode_use[P_SLICE][I4MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I8MB] - last_mode_use[P_SLICE][I8MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I16MB] - last_mode_use[P_SLICE][I16MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][0   ] - last_mode_use[P_SLICE][0   ]);
-
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][1   ] - last_mode_use[P_SLICE][1   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][2   ] - last_mode_use[P_SLICE][2   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][3   ] - last_mode_use[P_SLICE][3   ]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][0][1]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][0][1]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][0][2]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][0][2]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][0][3]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][0][3]);
-
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][P8x8] - last_mode_use[P_SLICE][P8x8]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][4   ] - last_mode_use[P_SLICE][4   ]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][0][4]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][0][4]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][5   ] - last_mode_use[P_SLICE][5   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][6   ] - last_mode_use[P_SLICE][6   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][7   ] - last_mode_use[P_SLICE][7   ]);
-
-  //B-Modes
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I4MB] - last_mode_use[B_SLICE][I4MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I8MB] - last_mode_use[B_SLICE][I8MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I16MB] - last_mode_use[B_SLICE][I16MB]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][0   ] - last_mode_use[B_SLICE][0   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][1   ] - last_mode_use[B_SLICE][1   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][2   ] - last_mode_use[B_SLICE][2   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][3   ] - last_mode_use[B_SLICE][3   ]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][1][0]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][1][0]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][1][1]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][1][1]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][1][2]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][1][2]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][1][3]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][1][3]);
-
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][P8x8] - last_mode_use[B_SLICE][P8x8]);
-  fprintf(p_stat_frm, " %d|", (stats->b8_mode_0_use [B_SLICE][0]+stats->b8_mode_0_use [B_SLICE][1]) - (last_b8_mode_0[B_SLICE][0]+last_b8_mode_0[B_SLICE][1]));
-  fprintf(p_stat_frm, " %5d|", stats->b8_mode_0_use [B_SLICE][1] - last_b8_mode_0[B_SLICE][1]);
-  fprintf(p_stat_frm, " %5d|", stats->b8_mode_0_use [B_SLICE][0] - last_b8_mode_0[B_SLICE][0]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][4   ] - last_mode_use[B_SLICE][4   ]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[1][1][4]);
-  fprintf(p_stat_frm, " %5d|", stats->mode_use_transform[0][1][4]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][5   ] - last_mode_use[B_SLICE][5   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][6   ] - last_mode_use[B_SLICE][6   ]);
-  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][7   ] - last_mode_use[B_SLICE][7   ]);
-
-  fprintf(p_stat_frm, "\n");
-
-  //save the last results
-  memcpy(last_mode_use[I_SLICE], stats->mode_use[I_SLICE], MAXMODE *  sizeof(int64));
-  memcpy(last_mode_use[P_SLICE], stats->mode_use[P_SLICE], MAXMODE *  sizeof(int64));
-  memcpy(last_mode_use[B_SLICE], stats->mode_use[B_SLICE], MAXMODE *  sizeof(int64));
-  memset(stats->mode_use_transform[1], 0, 2 * MAXMODE *  sizeof(int));
-  memset(stats->mode_use_transform[0], 0, 2 * MAXMODE *  sizeof(int));
-  memcpy(last_b8_mode_0[B_SLICE], stats->b8_mode_0_use[B_SLICE], 2 *  sizeof(int));
-  memcpy(last_mode_chroma_use, stats->intra_chroma_mode, 4 *  sizeof(int));
-
-  frame_statistic_start = 0;
-  fclose(p_stat_frm);
-}
-
-
-/*!
- ************************************************************************
- * \brief
- *    Reports the gathered information to appropriate outputs
- * \par Input:
- *    struct inp_par *inp,                                            \n
- *    ImageParameters *img,                                            \n
- *    struct stat_par *stats,                                          \n
- *    struct stat_par *stats                                           \n
- *
- * \par Output:
- *    None
- ************************************************************************
- */
-void report()
-{
-  int64 bit_use[NUM_PIC_TYPE][2] ;
-  int i,j;
-  char name[40];
-  int64 total_bits;
-  float frame_rate;
-  double mean_motion_info_bit_use[2] = {0.0};
-
-#ifndef WIN32
-  time_t now;
-  struct tm *l_time;
-  char string[1000];
-#else
-  char timebuf[128];
-#endif
-  bit_use[I_SLICE][0] = frame_ctr[I_SLICE];
-  bit_use[P_SLICE][0] = imax(frame_ctr[P_SLICE] + frame_ctr[SP_SLICE],1);
-  bit_use[B_SLICE][0] = frame_ctr[B_SLICE];
-
-  //  Accumulate bit usage for inter and intra frames
-  for (j=0; j < NUM_PIC_TYPE; j++)
-  {
-    bit_use[j][1] = 0;
-  }
-
-  for (j=0; j < NUM_PIC_TYPE; j++)
-  {
-    for(i=0; i < MAXMODE; i++)
-      bit_use[j][1] += stats->bit_use_mode[j][i];
-
-    bit_use[j][1] += stats->bit_use_header[j];
-    bit_use[j][1] += stats->bit_use_mb_type[j];
-    bit_use[j][1] += stats->tmp_bit_use_cbp[j];
-    bit_use[j][1] += stats->bit_use_coeffC[j];
-    bit_use[j][1] += stats->bit_use_coeff[0][j];   
-    bit_use[j][1] += stats->bit_use_coeff[1][j]; 
-    bit_use[j][1] += stats->bit_use_coeff[2][j]; 
-    bit_use[j][1] += stats->bit_use_delta_quant[j];
-    bit_use[j][1] += stats->bit_use_stuffingBits[j];
-  }
-
-  frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (params->jumpd+1);
-
-  //! Currently adding NVB bits on P rate. Maybe additional stats info should be created instead and added in log file
-  stats->bitrate_I = (stats->bit_ctr_I)*(frame_rate)/(float) (params->no_frames + frame_ctr[B_SLICE]);
-  stats->bitrate_P = (stats->bit_ctr_P)*(frame_rate)/(float) (params->no_frames + frame_ctr[B_SLICE]);
-  stats->bitrate_B = (stats->bit_ctr_B)*(frame_rate)/(float) (params->no_frames + frame_ctr[B_SLICE]);
-
-  switch (params->Verbose)
-  {
-  case 0:
-  case 1:
-  default:
-    fprintf(stdout,"------------------ Average data all frames  -----------------------------------\n\n");
-    break;
-  case 2:
-    fprintf(stdout,"------------------------------------  Average data all frames  ---------------------------------\n\n");
-    break;
-  }
-
-  if (params->Verbose != 0)
-  {
-    int  impix    = params->output.size_cmp[0];
-    int  impix_cr = params->output.size_cmp[1];
-    unsigned int max_pix_value_sqd = img->max_imgpel_value_comp[0] * img->max_imgpel_value_comp[0];
-    unsigned int max_pix_value_sqd_uv = img->max_imgpel_value_comp[1] * img->max_imgpel_value_comp[1];
-    float csnr_y = (float) (10 * log10 (max_pix_value_sqd *
-      (double)((double) impix / (snr->msse_y == 0.0? 1.0 : snr->msse_y))));
-    float csnr_u = (float) (10 * log10 (max_pix_value_sqd_uv *
-      (double)((double) impix_cr / (snr->msse_u == 0.0? 1.0 : snr->msse_u))));
-    float csnr_v = (float) (10 * log10 (max_pix_value_sqd_uv *
-      (double)((double) impix_cr / (snr->msse_v == 0.0? 1.0 : snr->msse_v))));
-    fprintf(stdout,  " Total encoding time for the seq.  : %.3f sec (%.2f fps)\n", tot_time*0.001, 1000.0*(params->no_frames + frame_ctr[B_SLICE])/tot_time);
-    fprintf(stdout,  " Total ME time for sequence        : %.3f sec \n\n", me_tot_time*0.001);
-
-    fprintf(stdout," PSNR Y(dB)                        : %5.2f\n", snr->snr_ya);
-    fprintf(stdout," PSNR U(dB)                        : %5.2f\n", snr->snr_ua);
-    fprintf(stdout," PSNR V(dB)                        : %5.2f\n", snr->snr_va);
-    fprintf(stdout," cSNR Y(dB)                        : %5.2f (%5.2f)\n", csnr_y,snr->msse_y/impix);
-    fprintf(stdout," cSNR U(dB)                        : %5.2f (%5.2f)\n", csnr_u,snr->msse_u/impix_cr);
-    fprintf(stdout," cSNR V(dB)                        : %5.2f (%5.2f)\n\n", csnr_v,snr->msse_v/impix_cr);
-  }
-  else
-    fprintf(stdout,  " Total encoding time for the seq.  : %.3f sec (%.2f fps)\n\n", tot_time*0.001, 1000.0*(params->no_frames + frame_ctr[B_SLICE])/tot_time);
-
-  if (frame_ctr[B_SLICE] != 0)
-  {
-    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", B %" FORMAT_OFF_T  " NVB %d) \n",
-      total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_B + stats->bit_ctr_parametersets,
-      stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_B, stats->bit_ctr_parametersets);
-
-    frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (params->jumpd+1);
-    //    stats->bitrate= ((float) total_bits * frame_rate)/((float) (params->no_frames + frame_ctr[B_SLICE]));
-    stats->bitrate= ((float) total_bits * frame_rate) / ((float)(frame_ctr[I_SLICE] + frame_ctr[P_SLICE] + frame_ctr[B_SLICE]));
-
-    fprintf(stdout, " Bit rate (kbit/s)  @ %2.2f Hz     : %5.2f\n", frame_rate, stats->bitrate/1000);
-
-  }
-  else if (params->sp_periodicity == 0)
-  {
-    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", NVB %d) \n",
-      total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_parametersets, stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_parametersets);
-
-
-    frame_rate = img->framerate / ( (float) (params->jumpd + 1) );
-    stats->bitrate= ((float) total_bits * frame_rate) / ((float) params->no_frames );
-
-    fprintf(stdout, " Bit rate (kbit/s)  @ %2.2f Hz     : %5.2f\n", frame_rate, stats->bitrate/1000);
-  }
-  else
-  {
-    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", NVB %d) \n",
-      total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_parametersets, stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_parametersets);
-
-
-    frame_rate = img->framerate / ( (float) (params->jumpd + 1) );
-    stats->bitrate= ((float) total_bits * frame_rate)/((float) params->no_frames );
-
-    fprintf(stdout, " Bit rate (kbit/s)  @ %2.2f Hz     : %5.2f\n", frame_rate, stats->bitrate/1000);
-  }
-
-  fprintf(stdout, " Bits to avoid Startcode Emulation : %d \n", stats->bit_ctr_emulationprevention);
-  fprintf(stdout, " Bits for parameter sets           : %d \n\n", stats->bit_ctr_parametersets);
-
-  switch (params->Verbose)
-  {
-  case 0:
-  case 1:
-  default:
-    fprintf(stdout,"-------------------------------------------------------------------------------\n");
-    break;
-  case 2:
-    fprintf(stdout,"------------------------------------------------------------------------------------------------\n");
-    break;
-  }  
-  fprintf(stdout,"Exit JM %s encoder ver %s ", JM, VERSION);
-  fprintf(stdout,"\n");
-
-  // status file
-  if (strlen(params->StatsFile) == 0)
-    strcpy (params->StatsFile,"stats.dat");
-
-  if ((p_stat = fopen(params->StatsFile, "wt")) == 0)
-  {
-    snprintf(errortext, ET_SIZE, "Error open file %s", params->StatsFile);
-    error(errortext, 500);
-  }
-
-  fprintf(p_stat," -------------------------------------------------------------- \n");
-  fprintf(p_stat,"  This file contains statistics for the last encoded sequence   \n");
-  fprintf(p_stat," -------------------------------------------------------------- \n");
-  fprintf(p_stat,   " Sequence                     : %s\n", params->infile);
-  fprintf(p_stat,   " No.of coded pictures         : %4d\n", params->no_frames+frame_ctr[B_SLICE]);
-  fprintf(p_stat,   " Freq. for encoded bitstream  : %4.0f\n", frame_rate);
-
-  fprintf(p_stat,   " I Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_I/1000);
-  fprintf(p_stat,   " P Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_P/1000);
-  // B pictures
-  if (stats->successive_Bframe != 0)
-    fprintf(p_stat,   " B Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_B/1000);
-  fprintf(p_stat,   " Total Bitrate(kb/s)          : %6.2f\n", stats->bitrate/1000);
-
-  for (i = 0; i < 3; i++)
-  {
-    fprintf(p_stat," ME Metric for Refinement Level %1d : %s\n", i, DistortionType[params->MEErrorMetric[i]]);
-  }
-  fprintf(p_stat," Mode Decision Metric             : %s\n", DistortionType[params->ModeDecisionMetric]);
-
-  switch ( params->ChromaMEEnable )
-  {
-  case 1:
-    fprintf(p_stat," Motion Estimation for components : YCbCr\n");
-    break;
-  default:
-    fprintf(p_stat," Motion Estimation for components : Y\n");
-    break;
-  }
-
-  fprintf(p_stat,  " Image format                 : %dx%d\n", params->output.width, params->output.height);
-
-  if (params->intra_upd)
-    fprintf(p_stat," Error robustness             : On\n");
-  else
-    fprintf(p_stat," Error robustness             : Off\n");
-
-  fprintf(p_stat,  " Search range                 : %d\n", params->search_range);
-
-  fprintf(p_stat,   " Total number of references   : %d\n", params->num_ref_frames);
-  fprintf(p_stat,   " References for P slices      : %d\n", params->P_List0_refs ? params->P_List0_refs : params->num_ref_frames);
-  if (stats->successive_Bframe != 0)
-  {
-    fprintf(p_stat, " List0 refs for B slices      : %d\n", params->B_List0_refs ? params->B_List0_refs : params->num_ref_frames);
-    fprintf(p_stat, " List1 refs for B slices      : %d\n", params->B_List1_refs ? params->B_List1_refs : params->num_ref_frames);
-  }
-
-  if (params->symbol_mode == CAVLC)
-    fprintf(p_stat,   " Entropy coding method        : CAVLC\n");
-  else
-    fprintf(p_stat,   " Entropy coding method        : CABAC\n");
-
-  fprintf(p_stat,   " Profile/Level IDC            : (%d,%d)\n", params->ProfileIDC, params->LevelIDC);
-  if (params->MbInterlace)
-    fprintf(p_stat, " MB Field Coding : On \n");
-
-  if (params->SearchMode == EPZS)
-    EPZSOutputStats(p_stat, 1);
-
-  if (params->full_search == 2)
-    fprintf(p_stat," Search range restrictions    : none\n");
-  else if (params->full_search == 1)
-    fprintf(p_stat," Search range restrictions    : older reference frames\n");
-  else
-    fprintf(p_stat," Search range restrictions    : smaller blocks and older reference frames\n");
-
-  if (params->rdopt)
-    fprintf(p_stat," RD-optimized mode decision   : used\n");
-  else
-    fprintf(p_stat," RD-optimized mode decision   : not used\n");
-
-  fprintf(p_stat," ---------------------|----------------|---------------|\n");
-  fprintf(p_stat,"     Item             |     Intra      |   All frames  |\n");
-  fprintf(p_stat," ---------------------|----------------|---------------|\n");
-  fprintf(p_stat," SNR Y(dB)            |");
-  fprintf(p_stat," %5.2f          |", snr->snr_y1);
-  fprintf(p_stat," %5.2f         |\n", snr->snr_ya);
-  fprintf(p_stat," SNR U/V (dB)         |");
-  fprintf(p_stat," %5.2f/%5.2f    |", snr->snr_u1, snr->snr_v1);
-  fprintf(p_stat," %5.2f/%5.2f   |\n", snr->snr_ua, snr->snr_va);
-
-  // QUANT.
-  fprintf(p_stat," Average quant        |");
-  fprintf(p_stat," %5d          |", iabs(params->qp0));
-  fprintf(p_stat," %5.2f         |\n", (float)stats->quant1/dmax(1.0,(float)stats->quant0));
-
-  fprintf(p_stat,"\n ---------------------|----------------|---------------|---------------|\n");
-  fprintf(p_stat,"     SNR              |        I       |       P       |       B       |\n");
-  fprintf(p_stat," ---------------------|----------------|---------------|---------------|\n");
-  fprintf(p_stat," SNR Y(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |\n",
-    snr->snr_yt[I_SLICE], snr->snr_yt[P_SLICE], snr->snr_yt[B_SLICE]);
-  fprintf(p_stat," SNR U(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |\n",
-    snr->snr_ut[I_SLICE], snr->snr_ut[P_SLICE], snr->snr_ut[B_SLICE]);
-  fprintf(p_stat," SNR V(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |\n",
-    snr->snr_vt[I_SLICE], snr->snr_vt[P_SLICE], snr->snr_vt[B_SLICE]);
-
-
-  // MODE
-  fprintf(p_stat,"\n ---------------------|----------------|\n");
-  fprintf(p_stat,"   Intra              |   Mode used    |\n");
-  fprintf(p_stat," ---------------------|----------------|\n");
-
-  fprintf(p_stat," Mode 0  intra 4x4    |  %5" FORMAT_OFF_T  "         |\n", stats->mode_use[I_SLICE][I4MB ]);
-  fprintf(p_stat," Mode 1  intra 8x8    |  %5" FORMAT_OFF_T  "         |\n", stats->mode_use[I_SLICE][I8MB ]);
-  fprintf(p_stat," Mode 2+ intra 16x16  |  %5" FORMAT_OFF_T  "         |\n", stats->mode_use[I_SLICE][I16MB]);
-  fprintf(p_stat," Mode    intra IPCM   |  %5" FORMAT_OFF_T  "         |\n", stats->mode_use[I_SLICE][IPCM ]);
-
-  fprintf(p_stat,"\n ---------------------|----------------|-----------------|\n");
-  fprintf(p_stat,"   Inter              |   Mode used    | MotionInfo bits |\n");
-  fprintf(p_stat," ---------------------|----------------|-----------------|");
-  fprintf(p_stat,"\n Mode  0  (copy)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[P_SLICE][0   ], (double)stats->bit_use_mode[P_SLICE][0   ]/(double)bit_use[P_SLICE][0]);
-  fprintf(p_stat,"\n Mode  1  (16x16)     |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[P_SLICE][1   ], (double)stats->bit_use_mode[P_SLICE][1   ]/(double)bit_use[P_SLICE][0]);
-  fprintf(p_stat,"\n Mode  2  (16x8)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[P_SLICE][2   ], (double)stats->bit_use_mode[P_SLICE][2   ]/(double)bit_use[P_SLICE][0]);
-  fprintf(p_stat,"\n Mode  3  (8x16)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[P_SLICE][3   ], (double)stats->bit_use_mode[P_SLICE][3   ]/(double)bit_use[P_SLICE][0]);
-  fprintf(p_stat,"\n Mode  4  (8x8)       |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[P_SLICE][P8x8], (double)stats->bit_use_mode[P_SLICE][P8x8]/(double)bit_use[P_SLICE][0]);
-  fprintf(p_stat,"\n Mode  5  intra 4x4   |  %5" FORMAT_OFF_T  "         |-----------------|", stats->mode_use[P_SLICE][I4MB]);
-  fprintf(p_stat,"\n Mode  6  intra 8x8   |  %5" FORMAT_OFF_T  "         |", stats->mode_use[P_SLICE][I8MB]);
-  fprintf(p_stat,"\n Mode  7+ intra 16x16 |  %5" FORMAT_OFF_T  "         |", stats->mode_use[P_SLICE][I16MB]);
-  fprintf(p_stat,"\n Mode     intra IPCM  |  %5" FORMAT_OFF_T  "         |", stats->mode_use[P_SLICE][IPCM ]);
-  mean_motion_info_bit_use[0] = (double)(stats->bit_use_mode[P_SLICE][0] + stats->bit_use_mode[P_SLICE][1] + stats->bit_use_mode[P_SLICE][2]
-  + stats->bit_use_mode[P_SLICE][3] + stats->bit_use_mode[P_SLICE][P8x8])/(double) bit_use[P_SLICE][0];
-
-  // B pictures
-  if ((stats->successive_Bframe!=0) && (frame_ctr[B_SLICE]!=0))
-  {
-
-    fprintf(p_stat,"\n\n ---------------------|----------------|-----------------|\n");
-    fprintf(p_stat,"   B frame            |   Mode used    | MotionInfo bits |\n");
-    fprintf(p_stat," ---------------------|----------------|-----------------|");
-    fprintf(p_stat,"\n Mode  0  (copy)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[B_SLICE][0   ], (double)stats->bit_use_mode[B_SLICE][0   ]/(double)frame_ctr[B_SLICE]);
-    fprintf(p_stat,"\n Mode  1  (16x16)     |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[B_SLICE][1   ], (double)stats->bit_use_mode[B_SLICE][1   ]/(double)frame_ctr[B_SLICE]);
-    fprintf(p_stat,"\n Mode  2  (16x8)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[B_SLICE][2   ], (double)stats->bit_use_mode[B_SLICE][2   ]/(double)frame_ctr[B_SLICE]);
-    fprintf(p_stat,"\n Mode  3  (8x16)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[B_SLICE][3   ], (double)stats->bit_use_mode[B_SLICE][3   ]/(double)frame_ctr[B_SLICE]);
-    fprintf(p_stat,"\n Mode  4  (8x8)       |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[B_SLICE][P8x8], (double)stats->bit_use_mode[B_SLICE][P8x8]/(double)frame_ctr[B_SLICE]);
-    fprintf(p_stat,"\n Mode  5  intra 4x4   |  %5" FORMAT_OFF_T  "         |-----------------|", stats->mode_use[B_SLICE][I4MB]);
-    fprintf(p_stat,"\n Mode  6  intra 8x8   |  %5" FORMAT_OFF_T  "         |", stats->mode_use[B_SLICE][I8MB]);
-    fprintf(p_stat,"\n Mode  7+ intra 16x16 |  %5" FORMAT_OFF_T  "         |", stats->mode_use[B_SLICE][I16MB]);
-    fprintf(p_stat,"\n Mode     intra IPCM  |  %5" FORMAT_OFF_T  "         |", stats->mode_use[B_SLICE][IPCM ]);
-    mean_motion_info_bit_use[1] = (double)(stats->bit_use_mode[B_SLICE][0] + stats->bit_use_mode[B_SLICE][1] + stats->bit_use_mode[B_SLICE][2]
-    + stats->bit_use_mode[B_SLICE][3] + stats->bit_use_mode[B_SLICE][P8x8])/(double) frame_ctr[B_SLICE];
-  }
-
-  fprintf(p_stat,"\n\n ---------------------|----------------|----------------|----------------|\n");
-  fprintf(p_stat,"  Bit usage:          |      Intra     |      Inter     |    B frame     |\n");
-  fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
-
-  fprintf(p_stat," Header               |");
-  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[I_SLICE]/bit_use[I_SLICE][0]);
-  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[P_SLICE]/bit_use[P_SLICE][0]);
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[B_SLICE]/frame_ctr[B_SLICE]);
-  else fprintf(p_stat," %10.2f     |", 0.);
-  fprintf(p_stat,"\n");
-
-  fprintf(p_stat," Mode                 |");
-  fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[I_SLICE]/bit_use[I_SLICE][0]);
-  fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[P_SLICE]/bit_use[P_SLICE][0]);
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[B_SLICE]/frame_ctr[B_SLICE]);
-  else fprintf(p_stat," %10.2f     |", 0.);
-  fprintf(p_stat,"\n");
-
-  fprintf(p_stat," Motion Info          |");
-  fprintf(p_stat,"        ./.     |");
-  fprintf(p_stat," %10.2f     |", mean_motion_info_bit_use[0]);
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," %10.2f     |", mean_motion_info_bit_use[1]);
-  else fprintf(p_stat," %10.2f     |", 0.);
-  fprintf(p_stat,"\n");
-
-  fprintf(p_stat," CBP Y/C              |");
-  fprintf(p_stat," %10.2f     |", (float)stats->tmp_bit_use_cbp[I_SLICE]/bit_use[I_SLICE][0]);
-  fprintf(p_stat," %10.2f     |", (float)stats->tmp_bit_use_cbp[P_SLICE]/bit_use[P_SLICE][0]);
-  if ((stats->successive_Bframe != 0) && (bit_use[B_SLICE][0] != 0))
-    fprintf(p_stat," %10.2f     |", (float)stats->tmp_bit_use_cbp[B_SLICE]/bit_use[B_SLICE][0]);
-  else fprintf(p_stat," %10.2f     |", 0.);
-  fprintf(p_stat,"\n");
-
-  if (stats->successive_Bframe != 0 && frame_ctr[B_SLICE] != 0)
-    fprintf(p_stat," Coeffs. Y            | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_coeff[0][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[0][P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeff[0][B_SLICE]/frame_ctr[B_SLICE]);
-  else
-    fprintf(p_stat," Coeffs. Y            | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_coeff[0][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[0][P_SLICE]/(float)bit_use[P_SLICE][0], 0.);
-
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," Coeffs. C            | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_coeffC[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffC[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeffC[B_SLICE]/frame_ctr[B_SLICE]);
-  else
-    fprintf(p_stat," Coeffs. C            | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_coeffC[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffC[P_SLICE]/bit_use[P_SLICE][0], 0.);
-  if(img->P444_joined) 
-  {
-    if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
-      fprintf(p_stat," Coeffs. CB           | %10.2f     | %10.2f     | %10.2f     |\n",
-      (float)stats->bit_use_coeff[1][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[1][P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeff[1][B_SLICE]/frame_ctr[B_SLICE]);
-    else
-      fprintf(p_stat," Coeffs. CB           | %10.2f     | %10.2f     | %10.2f     |\n",
-      (float)stats->bit_use_coeff[1][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[1][P_SLICE]/bit_use[P_SLICE][0], 0.);
-
-    if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
-      fprintf(p_stat," Coeffs. CR           | %10.2f     | %10.2f     | %10.2f     |\n",
-      (float)stats->bit_use_coeff[2][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[2][P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeff[2][B_SLICE]/frame_ctr[B_SLICE]);
-    else
-      fprintf(p_stat," Coeffs. CR           | %10.2f     | %10.2f     | %10.2f     |\n",
-      (float)stats->bit_use_coeff[2][I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeff[2][P_SLICE]/bit_use[P_SLICE][0], 0.);
-  }
-
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," Delta quant          | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_delta_quant[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_delta_quant[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_delta_quant[B_SLICE]/frame_ctr[B_SLICE]);
-  else
-    fprintf(p_stat," Delta quant          | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_delta_quant[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_delta_quant[P_SLICE]/bit_use[P_SLICE][0], 0.);
-
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0))
-    fprintf(p_stat," Stuffing Bits        | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_stuffingBits[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_stuffingBits[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_stuffingBits[B_SLICE]/frame_ctr[B_SLICE]);
-  else
-    fprintf(p_stat," Stuffing Bits        | %10.2f     | %10.2f     | %10.2f     |\n",
-    (float)stats->bit_use_stuffingBits[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_stuffingBits[P_SLICE]/bit_use[P_SLICE][0], 0.);
-
-
-
-  fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
-
-  fprintf(p_stat," average bits/frame   |");
-
-  fprintf(p_stat," %10.2f     |", (float) bit_use[I_SLICE][1]/(float) bit_use[I_SLICE][0] );
-  fprintf(p_stat," %10.2f     |", (float) bit_use[P_SLICE][1]/(float) bit_use[P_SLICE][0] );
-
-  if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
-    fprintf(p_stat," %10.2f     |", (float) bit_use[B_SLICE][1]/ (float) frame_ctr[B_SLICE] );
-  else fprintf(p_stat," %10.2f     |", 0.);
-
-  fprintf(p_stat,"\n");
-  fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
-
-  fclose(p_stat);
-
-  // write to log file
-  if ((p_log = fopen("log.dat", "r")) == 0)         // check if file exists
-  {
-    if ((p_log = fopen("log.dat", "a")) == NULL)    // append new statistic at the end
-    {
-      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log.dat");
-      error(errortext, 500);
-    }
-    else                                            // Create header for new log file
-    {
-      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
-      fprintf(p_log,"|                          Encoder statistics. This file is generated during first encoding session, new sessions will be appended                                                                                                                                                                                 |\n");
-      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
-      fprintf(p_log,"|     ver     | Date  | Time  |               Sequence                 | #Img |P/MbInt| QPI| QPP| QPB| Format  |Iperiod| #B | FMES | Hdmd | S.R |#Ref | Freq |Coding|RD-opt|Intra upd|8x8Tr| SNRY 1| SNRU 1| SNRV 1| SNRY N| SNRU N| SNRV N|#Bitr I|#Bitr P|#Bitr B|#Bitr IPB|     Total Time   |      Me Time     |\n");
-      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
-
-    }
-  }
-  else
-  {
-    fclose (p_log);
-    if ((p_log = fopen("log.dat", "a")) == NULL)         // File exists, just open for appending
-    {
-      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log.dat");
-      error(errortext, 500);
-    }
-  }
-  fprintf(p_log,"|%5s/%-5s", VERSION, EXT_VERSION);
-
-#ifdef WIN32
-  _strdate( timebuf );
-  fprintf(p_log,"| %1.5s |", timebuf );
-
-  _strtime( timebuf);
-  fprintf(p_log," % 1.5s |", timebuf);
-#else
-  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
-  time (&now);
-  l_time = localtime (&now);
-  strftime (string, sizeof string, "%d-%b-%Y", l_time);
-  fprintf(p_log,"| %1.5s |", string );
-
-  strftime (string, sizeof string, "%H:%M:%S", l_time);
-  fprintf(p_log," %1.5s |", string );
-#endif
-
-  for (i=0; i < 40; i++)
-    name[i] = params->infile[i + imax(0, ((int) strlen(params->infile)) - 40)]; // write last part of path, max 40 chars
-  fprintf(p_log,"%40.40s|",name);
-
-  fprintf(p_log,"%5d |  %d/%d  |", params->no_frames, params->PicInterlace, params->MbInterlace);
-  fprintf(p_log," %-3d| %-3d| %-3d|", params->qp0, params->qpN, params->qpB);
-
-  fprintf(p_log,"%4dx%-4d|", params->output.width, params->output.height);
-  fprintf(p_log,"  %3d  |%3d |", params->intra_period, stats->successive_Bframe);
-
-
-  switch( params->SearchMode ) 
-  {
-    case UM_HEX:
-      fprintf(p_log,"  HEX |");
-      break;
-    case UM_HEX_SIMPLE:
-      fprintf(p_log," SHEX |");
-      break;
-    case EPZS:
-      fprintf(p_log," EPZS |");
-      break;
-    case FAST_FULL_SEARCH:
-      fprintf(p_log,"  FFS |");
-      break;
-    default:
-      fprintf(p_log,"  FS  |");
-      break;
-  }
-
-  fprintf(p_log,"  %1d%1d%1d |", params->MEErrorMetric[F_PEL], params->MEErrorMetric[H_PEL], params->MEErrorMetric[Q_PEL]);
-
-  fprintf(p_log," %3d | %2d  |", params->search_range, params->num_ref_frames );
-
-  fprintf(p_log," %5.2f|", (img->framerate *(float) (stats->successive_Bframe + 1)) / (float)(params->jumpd + 1));
-
-  if (params->symbol_mode == CAVLC)
-    fprintf(p_log," CAVLC|");
-  else
-    fprintf(p_log," CABAC|");
-
-  fprintf(p_log,"   %d  |", params->rdopt);
-
-  if (params->intra_upd == 1)
-    fprintf(p_log,"   ON    |");
-  else
-    fprintf(p_log,"   OFF   |");
-
-  fprintf(p_log,"  %d  |", params->Transform8x8Mode);
-
-  fprintf(p_log,"%7.3f|%7.3f|%7.3f|", snr->snr_y1,snr->snr_u1,snr->snr_v1);
-  fprintf(p_log,"%7.3f|%7.3f|%7.3f|", snr->snr_ya,snr->snr_ua,snr->snr_va);
-  /*
-  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", snr->snr_yt[I_SLICE], snr->snr_ut[I_SLICE], snr->snr_vt[I_SLICE]);
-  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", snr->snr_yt[P_SLICE], snr->snr_ut[P_SLICE], snr->snr_vt[P_SLICE]);
-  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", snr->snr_yt[B_SLICE], snr->snr_ut[B_SLICE], snr->snr_vt[B_SLICE]);
-  */
-  fprintf(p_log,"%7.0f|%7.0f|%7.0f|%9.0f|", stats->bitrate_I,stats->bitrate_P,stats->bitrate_B, stats->bitrate);
-
-  fprintf(p_log,"   %12d   |   %12d   |", (int)tot_time,(int)me_tot_time);
-
-
-  fprintf(p_log,"\n");
-
-  fclose(p_log);
-
-  p_log = fopen("data.txt", "a");
-
-  if ((stats->successive_Bframe != 0) && (frame_ctr[B_SLICE] != 0)) // B picture used
-  {
-    fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " "
-      "%2.2f %2.2f %2.2f %5d "
-      "%2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " %5" FORMAT_OFF_T  " %.3f\n",
-      params->no_frames, params->qp0, params->qpN,
-      snr->snr_y1,
-      snr->snr_u1,
-      snr->snr_v1,
-      stats->bit_ctr_I,
-      0.0,
-      0.0,
-      0.0,
-      0,
-      snr->snr_ya,
-      snr->snr_ua,
-      snr->snr_va,
-      (stats->bit_ctr_I+stats->bit_ctr)/(params->no_frames+frame_ctr[B_SLICE]),
-      stats->bit_ctr_B/frame_ctr[B_SLICE],
-      (double)0.001*tot_time/(params->no_frames+frame_ctr[B_SLICE]));
-  }
-  else
-  {
-    if (params->no_frames != 0)
-      fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " "
-      "%2.2f %2.2f %2.2f %5d "
-      "%2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " %5d %.3f\n",
-      params->no_frames, params->qp0, params->qpN,
-      snr->snr_y1,
-      snr->snr_u1,
-      snr->snr_v1,
-      stats->bit_ctr_I,
-      0.0,
-      0.0,
-      0.0,
-      0,
-      snr->snr_ya,
-      snr->snr_ua,
-      snr->snr_va,
-      (stats->bit_ctr_I+stats->bit_ctr)/params->no_frames,
-      0,
-      (double)0.001*tot_time/params->no_frames);
-  }
-
-  fclose(p_log);
-
-  if (params->ReportFrameStats)
-  {
-    if ((p_log = fopen("stat_frame.dat", "a")) == NULL)       // append new statistic at the end
-    {
-      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
-      //    error(errortext, 500);
-    }
-    else
-    {
-      fprintf(p_log," --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
-      fclose(p_log);
-    }
-  }
-}
-
-
-/*!
- ************************************************************************
- * \brief
- *    Prints the header of the protocol.
- * \par Input:
- *    struct inp_par *inp
- * \par Output:
- *    none
- ************************************************************************
- */
-void information_init(void)
-{
-  int i;
-  static char yuv_types[4][10] = {"YUV 4:0:0", "YUV 4:2:0", "YUV 4:2:2", "YUV 4:4:4"};
-  switch (params->Verbose)
-  {
-  case 0:
-  case 1:
-  default:
-    printf("------------------------------- JM %4.4s %7.7s -------------------------------\n", VERSION, EXT_VERSION);
-    break;
-  case 2:
-    printf("--------------------------------------- JM %4.4s %7.7s ----------------------------------------\n", VERSION, EXT_VERSION);
-    break;
-  }
-
-  fprintf(stdout,  " Input YUV file                    : %s \n", params->infile);
-  fprintf(stdout,  " Output H.264 bitstream            : %s \n", params->outfile);
-  if (p_dec != -1)
-    fprintf(stdout,  " Output YUV file                   : %s \n", params->ReconFile);
-  fprintf(stdout,  " YUV Format                        : %s \n", &yuv_types[img->yuv_format][0]);//img->yuv_format==YUV422?"YUV 4:2:2":(img->yuv_format==YUV444)?"YUV 4:4:4":"YUV 4:2:0");
-  fprintf(stdout,  " Frames to be encoded I-P/B        : %d/%d\n", params->no_frames, (params->successive_Bframe*(params->no_frames-1)));
-  if (params->Verbose != 0)
-  {
-    fprintf(stdout,  " Freq. for encoded bitstream       : %1.0f\n", img->framerate/(float)(params->jumpd+1));
-    fprintf(stdout,  " PicInterlace / MbInterlace        : %d/%d\n", params->PicInterlace, params->MbInterlace);
-    fprintf(stdout,  " Transform8x8Mode                  : %d\n", params->Transform8x8Mode);
-
-    for (i=0; i<3; i++)
-    {
-      fprintf(stdout," ME Metric for Refinement Level %1d  : %s\n", i, DistortionType[params->MEErrorMetric[i]]);
-    }
-    fprintf(stdout,  " Mode Decision Metric              : %s\n", DistortionType[params->ModeDecisionMetric]);
-
-    switch ( params->ChromaMEEnable )
-    {
-    case 1:
-      fprintf(stdout," Motion Estimation for components  : YCbCr\n");
-      break;
-    default:
-      fprintf(stdout," Motion Estimation for components  : Y\n");
-      break;
-    }
-
-    fprintf(stdout,  " Image format                      : %dx%d (%dx%d)\n", params->output.width, params->output.height, img->width,img->height);
-
-    if (params->intra_upd)
-      fprintf(stdout," Error robustness                  : On\n");
-    else
-      fprintf(stdout," Error robustness                  : Off\n");
-    fprintf(stdout,  " Search range                      : %d\n", params->search_range);
-
-    fprintf(stdout,  " Total number of references        : %d\n", params->num_ref_frames);
-    fprintf(stdout,  " References for P slices           : %d\n", params->P_List0_refs? params->P_List0_refs:params->num_ref_frames);
-    if (stats->successive_Bframe != 0)
-    {
-      fprintf(stdout," List0 references for B slices     : %d\n", params->B_List0_refs? params->B_List0_refs:params->num_ref_frames);
-      fprintf(stdout," List1 references for B slices     : %d\n", params->B_List1_refs? params->B_List1_refs:params->num_ref_frames);
-    }
-
-    // B pictures
-    fprintf(stdout,  " Sequence type                     :");
-
-    if (stats->successive_Bframe > 0 && params->HierarchicalCoding)
-    {
-      fprintf(stdout, " Hierarchy (QP: I %d, P %d, B %d) \n",
-        params->qp0, params->qpN, params->qpB);
-    }
-    else if (stats->successive_Bframe > 0)
-    {
-      char seqtype[80];
-      int i,j;
-
-      strcpy (seqtype,"I");
-
-      for (j=0; j < 2; j++)
-      {
-        for (i=0; i < stats->successive_Bframe; i++)
-        {
-          if (params->BRefPictures)
-            strncat(seqtype,"-RB", imax(0, (int) (79-strlen(seqtype))));
-          else
-            strncat(seqtype,"-B", imax(0, (int) (79-strlen(seqtype))));
-        }
-        strncat(seqtype,"-P", imax(0, (int) (79-strlen(seqtype))));
-      }
-      if (params->BRefPictures)
-        fprintf(stdout, " %s (QP: I %d, P %d, RB %d) \n", seqtype, params->qp0, params->qpN, iClip3(0, 51, params->qpB + params->qpBRSOffset));
-      else
-        fprintf(stdout, " %s (QP: I %d, P %d, B %d) \n", seqtype, params->qp0, params->qpN, params->qpB);
-    }
-    else if (stats->successive_Bframe == 0 && params->sp_periodicity == 0) fprintf(stdout, " IPPP (QP: I %d, P %d) \n", params->qp0, params->qpN);
-
-    else fprintf(stdout, " I-P-P-SP-P (QP: I %d, P %d, SP (%d, %d)) \n",  params->qp0, params->qpN, params->qpsp, params->qpsp_pred);
-
-    // report on entropy coding  method
-    if (params->symbol_mode == CAVLC)
-      fprintf(stdout," Entropy coding method             : CAVLC\n");
-    else
-      fprintf(stdout," Entropy coding method             : CABAC\n");
-
-    fprintf(stdout,  " Profile/Level IDC                 : (%d,%d)\n", params->ProfileIDC, params->LevelIDC);
-
-    if (params->SearchMode == UM_HEX)
-      fprintf(stdout,  " Motion Estimation Scheme          : HEX\n");
-    else if (params->SearchMode == UM_HEX_SIMPLE)
-      fprintf(stdout,  " Motion Estimation Scheme          : SHEX\n");
-    else if (params->SearchMode == EPZS)
-    {
-      fprintf(stdout,  " Motion Estimation Scheme          : EPZS\n");
-      EPZSOutputStats(stdout, 0);
-    }
-    else if (params->SearchMode == FAST_FULL_SEARCH)
-      fprintf(stdout,  " Motion Estimation Scheme          : Fast Full Search\n");
-    else
-      fprintf(stdout,  " Motion Estimation Scheme          : Full Search\n");
-
-    if (params->full_search == 2)
-      fprintf(stdout," Search range restrictions         : none\n");
-    else if (params->full_search == 1)
-      fprintf(stdout," Search range restrictions         : older reference frames\n");
-    else
-      fprintf(stdout," Search range restrictions         : smaller blocks and older reference frames\n");
-
-    if (params->rdopt)
-      fprintf(stdout," RD-optimized mode decision        : used\n");
-    else
-      fprintf(stdout," RD-optimized mode decision        : not used\n");
-
-    switch(params->partition_mode)
-    {
-    case PAR_DP_1:
-      fprintf(stdout," Data Partitioning Mode            : 1 partition \n");
-      break;
-    case PAR_DP_3:
-      fprintf(stdout," Data Partitioning Mode            : 3 partitions \n");
-      break;
-    default:
-      fprintf(stdout," Data Partitioning Mode            : not supported\n");
-      break;
-    }
-
-    switch(params->of_mode)
-    {
-    case PAR_OF_ANNEXB:
-      fprintf(stdout," Output File Format                : H.264/AVC Annex B Byte Stream Format \n");
-      break;
-    case PAR_OF_RTP:
-      fprintf(stdout," Output File Format                : RTP Packet File Format \n");
-      break;
-    default:
-      fprintf(stdout," Output File Format                : not supported\n");
-      break;
-    }
-  }
-
-
-  switch (params->Verbose)
-  {
-  case 0:
-  default:
-    printf("-------------------------------------------------------------------------------\n");
-    printf("\nEncoding. Please Wait.\n\n");
-    break;    
-  case 1:
-    printf("-------------------------------------------------------------------------------\n");
-    printf("  Frame  Bit/pic    QP   SnrY    SnrU    SnrV    Time(ms) MET(ms) Frm/Fld Ref  \n");
-    printf("-------------------------------------------------------------------------------\n");
-    break;
-  case 2:
-    printf("------------------------------------------------------------------------------------------------\n");
-    printf("  Frame  Bit/pic WP QP QL   SnrY    SnrU    SnrV    Time(ms) MET(ms) Frm/Fld   I D L0 L1 RDP Ref\n");
-    printf("------------------------------------------------------------------------------------------------\n");
-    break;
-  }
-}
 
 /*!
  ************************************************************************
@@ -2034,46 +1017,41 @@ int init_orig_buffers(void)
   int memory_size = 0;
   int nplane;
 
-  // allocate memory for reference frame buffers: imgY_org_frm, imgUV_org_frm
+  // allocate memory for reference frame buffers: img_org_frm
   if( IS_INDEPENDENT(params) )
   {
     for( nplane=0; nplane<MAX_PLANE; nplane++ )
     {
-      memory_size += get_mem2Dpel(&imgY_org_frm_JV[nplane], img->height, img->width);
+      memory_size += get_mem2Dpel(&img_org_frm[nplane], img->height, img->width);
     }
   }
   else
   {
-    memory_size += get_mem2Dpel(&imgY_org_frm, img->height, img->width);
-  }
-
-  if (img->yuv_format != YUV400)
-  {
-    int i, j, k;
-    memory_size += get_mem3Dpel(&imgUV_org_frm, 2, img->height_cr, img->width_cr);
-    for (k = 0; k < 2; k++)
-      for (j = 0; j < img->height_cr; j++)
-        for (i = 0; i < img->width_cr; i++)
-          imgUV_org_frm[k][j][i] = 128;
+    memory_size += get_mem2Dpel(&img_org_frm[0], img->height, img->width);
+    if (img->yuv_format != YUV400)
+    {
+      int i, j, k;
+      memory_size += get_mem2Dpel(&img_org_frm[1], img->height_cr, img->width_cr);
+      memory_size += get_mem2Dpel(&img_org_frm[2], img->height_cr, img->width_cr);
+      for (k = 1; k < 3; k++)
+        for (j = 0; j < img->height_cr; j++)
+          for (i = 0; i < img->width_cr; i++)
+            img_org_frm[k][j][i] = 128;
+    }
   }
 
-
   if (!active_sps->frame_mbs_only_flag)
   {
-    // allocate memory for reference frame buffers: imgY_org, imgUV_org
-    init_top_bot_planes(imgY_org_frm, img->height, img->width, &imgY_org_top, &imgY_org_bot);
+    // allocate memory for field reference frame buffers
+    init_top_bot_planes(img_org_frm[0], img->height, img->width, &img_org_top[0], &img_org_bot[0]);
 
     if (img->yuv_format != YUV400)
     {
-      if ((imgUV_org_top = (imgpel***)calloc(2, sizeof(imgpel**))) == NULL)
-        no_mem_exit("init_global_buffers: imgUV_org_top");
-      if ((imgUV_org_bot = (imgpel***)calloc(2, sizeof(imgpel**))) == NULL)
-        no_mem_exit("init_global_buffers: imgUV_org_bot");
 
       memory_size += 4*(sizeof(imgpel**));
 
-      memory_size += init_top_bot_planes(imgUV_org_frm[0], img->height_cr, img->width_cr, &(imgUV_org_top[0]), &(imgUV_org_bot[0]));
-      memory_size += init_top_bot_planes(imgUV_org_frm[1], img->height_cr, img->width_cr, &(imgUV_org_top[1]), &(imgUV_org_bot[1]));
+      memory_size += init_top_bot_planes(img_org_frm[1], img->height_cr, img->width_cr, &(img_org_top[1]), &(img_org_bot[1]));
+      memory_size += init_top_bot_planes(img_org_frm[2], img->height_cr, img->width_cr, &(img_org_top[2]), &(img_org_bot[2]));
     }
   }
   return memory_size;
@@ -2175,18 +1153,10 @@ int init_global_buffers(void)
 
   if (params->rdopt == 3)
   {
-    memory_size += get_mem2Dint(&decs->resY, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
-    if ((decs->decref = (imgpel****) calloc(params->NoOfDecoders, sizeof(imgpel***))) == NULL)
-      no_mem_exit("init_global_buffers: decref");
-    for (j = 0; j < params->NoOfDecoders; j++)
-    {
-      memory_size += get_mem3Dpel(&decs->decref[j], img->max_num_references+1, img->height, img->width);
-    }
-    memory_size += get_mem2Dpel(&decs->RefBlock, BLOCK_SIZE, BLOCK_SIZE);
-    memory_size += get_mem3Dpel(&decs->decY, params->NoOfDecoders, img->height, img->width);
-    memory_size += get_mem3Dpel(&decs->decY_best, params->NoOfDecoders, img->height, img->width);
-    memory_size += get_mem2D(&decs->status_map,  img->FrameHeightInMbs, img->PicWidthInMbs);
-    memory_size += get_mem2D(&decs->dec_mb_mode, img->FrameHeightInMbs, img->PicWidthInMbs);
+    decs->dec_mbY = NULL;
+    decs->dec_mbY8x8 = NULL;
+    memory_size += get_mem3Dpel(&decs->dec_mbY, params->NoOfDecoders, 16, 16);
+    memory_size += get_mem3Dpel(&decs->dec_mbY8x8, params->NoOfDecoders, 16, 16);
   }
   if (params->RestrictRef)
   {
@@ -2217,7 +1187,7 @@ int init_global_buffers(void)
       memory_size += smpUMHEX_get_mem();
     }
     else if (params->SearchMode == EPZS)
-      memory_size += EPZSInit();
+      memory_size += EPZSInit(params, img);
   }
 
   if (params->RCEnable)
@@ -2245,6 +1215,25 @@ int init_global_buffers(void)
   img_cr_padded_size_x2   = (img_cr_padded_size_x << 1);
   img_cr_padded_size_x4   = (img_cr_padded_size_x << 2);
   img_cr_padded_size_x_m8 = (img_cr_padded_size_x - 8);
+
+  // RGB images for distortion calculation
+  // Recommended to do this allocation (and de-allocation) in 
+  // the appropriate file instead of here.
+  if(params->DistortionYUVtoRGB)
+  {
+    for( j = 0; j < 3; j++ )
+    {
+      memory_size += get_mem2Dpel (&imgRGB_src.data[j], img->height, img->width);
+      memory_size += get_mem2Dpel (&imgRGB_ref.data[j], img->height, img->width);
+    }
+  }
+
+  pWPX = NULL;
+  if ( params->WPMCPrecision )
+  {
+    wpxInitWPXObject();
+  }
+
   return memory_size;
 }
 
@@ -2262,28 +1251,27 @@ void free_orig_planes(void)
     int nplane;
     for( nplane=0; nplane<MAX_PLANE; nplane++ )
     {
-      free_mem2Dpel(imgY_org_frm_JV[nplane]);      // free ref frame buffers
+      free_mem2Dpel(img_org_frm[nplane]);      // free ref frame buffers
     }
   }
   else
   {
-    free_mem2Dpel(imgY_org_frm);      // free ref frame buffers
+    free_mem2Dpel(img_org_frm[0]);      // free ref frame buffers
+    if (img->yuv_format != YUV400)
+    {
+      free_mem2Dpel(img_org_frm[1]);
+      free_mem2Dpel(img_org_frm[2]);
+    }
   }
 
-  if (img->yuv_format != YUV400)
-    free_mem3Dpel(imgUV_org_frm);
-
-
   if (!active_sps->frame_mbs_only_flag)
   {
-    free_top_bot_planes(imgY_org_top, imgY_org_bot);
+    free_top_bot_planes(img_org_top[0], img_org_bot[0]);
 
     if (img->yuv_format != YUV400)
     {
-      free_top_bot_planes(imgUV_org_top[0], imgUV_org_bot[0]);
-      free_top_bot_planes(imgUV_org_top[1], imgUV_org_bot[1]);
-      free (imgUV_org_top);
-      free (imgUV_org_bot);
+      free_top_bot_planes(img_org_top[1], img_org_bot[1]);
+      free_top_bot_planes(img_org_top[2], img_org_bot[2]);
     }
   }
 }
@@ -2353,6 +1341,11 @@ void free_global_buffers(void)
   free_QMatrix();
   free_QOffsets();
 
+  if ( params->WPMCPrecision )
+  {
+    wpxFreeWPXObject();
+  }
+
   if (params->WeightedPrediction || params->WeightedBiprediction || params->GenerateMultiplePPS)
   {
     free_mem3Dint(wp_weight );
@@ -2376,7 +1369,8 @@ void free_global_buffers(void)
   // free intra pred mode buffer for blocks
   free_mem2D((byte**)img->ipredmode);
   free_mem2D((byte**)img->ipredmode8x8);
-  
+  free(img->b8x8info);
+
   if( IS_INDEPENDENT(params) )
   {
     for( i=0; i<MAX_PLANE; i++ ){
@@ -2404,37 +1398,16 @@ void free_global_buffers(void)
 
   if (params->rdopt == 3)
   {
-    free(decs->resY[0]);
-    free(decs->resY);
-
-    free(decs->RefBlock[0]);
-    free(decs->RefBlock);
-
-    for (j=0; j < params->NoOfDecoders; j++)
+    if (decs->dec_mbY)
     {
-      free(decs->decY[j][0]);
-      free(decs->decY[j]);
-
-      free(decs->decY_best[j][0]);
-      free(decs->decY_best[j]);
-
-      for (i=0; i < img->max_num_references+1; i++)
-      {
-        free(decs->decref[j][i][0]);
-        free(decs->decref[j][i]);
-      }
-      free(decs->decref[j]);
+       free_mem3Dpel(decs->dec_mbY);
+    }
+    if (decs->dec_mbY8x8)
+    {	
+       free_mem3Dpel(decs->dec_mbY8x8);
     }
-    free(decs->decY);
-    free(decs->decY_best);
-    free(decs->decref);
-
-    free(decs->status_map[0]);
-    free(decs->status_map);
-
-    free(decs->dec_mb_mode[0]);
-    free(decs->dec_mb_mode);
   }
+
   if (params->RestrictRef)
   {
     free(pixel_map[0]);
@@ -2454,13 +1427,14 @@ void free_global_buffers(void)
 
   free_mem3Dint(img->nz_coeff);
 
-  free_mem2Ddb_offset (img->lambda_md, img->bitdepth_luma_qp_scale);
-  free_mem3Ddb_offset (img->lambda_me, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
-  free_mem3Dint_offset(img->lambda_mf, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
+  free_mem2Dolm     (img->lambda, img->bitdepth_luma_qp_scale);
+  free_mem2Dodouble (img->lambda_md, img->bitdepth_luma_qp_scale);
+  free_mem3Dodouble (img->lambda_me, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
+  free_mem3Doint    (img->lambda_mf, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
 
   if (params->CtxAdptLagrangeMult == 1)
   {
-    free_mem2Ddb_offset(img->lambda_mf_factor, img->bitdepth_luma_qp_scale);
+    free_mem2Dodouble(img->lambda_mf_factor, img->bitdepth_luma_qp_scale);
   }
 
   if (!params->IntraProfile)
@@ -2475,7 +1449,7 @@ void free_global_buffers(void)
     }
     else if (params->SearchMode == EPZS)
     {
-      EPZSDelete();
+      EPZSDelete(params);
     }
   }
 
@@ -2489,6 +1463,17 @@ void free_global_buffers(void)
     free_mem2Dpel(imgUV_tmp[0]);
     free_mem2Dpel(imgUV_tmp[1]);
   }
+
+  // Again process should be moved into cconv_yuv2rgb.c file for cleanliness
+  // These should not be globals but instead only be visible through that code.
+  if(params->DistortionYUVtoRGB)
+  {
+    for( i = 0; i < 3; i++ )
+    {
+      free_mem2Dpel(imgRGB_src.data[i]);
+      free_mem2Dpel(imgRGB_ref.data[i]);
+    }
+  }  
 }
 
 /*!
@@ -2509,6 +1494,27 @@ int get_mem_mv (short ******* mv)
   return 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short);
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate memory for bipredictive mv 
+ * \par Input:
+ *    Image Parameters ImageParameters *img                             \n
+ *    int****** mv
+ * \return memory size in bytes
+ ************************************************************************
+ */
+int get_mem_bipred_mv (short******** bipred_mv) 
+{
+  if(((*bipred_mv) = (short*******)calloc(2, sizeof(short******))) == NULL)
+    no_mem_exit("get_mem_bipred_mv: bipred_mv");
+  
+  get_mem6Dshort(*bipred_mv, 2 * 2, img->max_num_references, 9, 4, 4, 2);
+  (*bipred_mv)[1] =  (*bipred_mv)[0] + 2;
+  
+  return 2 * 2 * img->max_num_references * 9 * 4 * 4 * 2 * sizeof(short);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -2523,6 +1529,27 @@ void free_mem_mv (short****** mv)
 }
 
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Free memory from mv
+ * \par Input:
+ *    int****** mv
+ ************************************************************************
+ */
+void free_mem_bipred_mv (short******* bipred_mv) 
+{
+  if (bipred_mv)
+  {
+    free_mem6Dshort(*bipred_mv);
+    free (bipred_mv);
+  }
+  else
+  {
+    error ("free_mem_bipred_mv: trying to free unused memory",100);
+  }
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -2626,7 +1653,7 @@ int decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bi
  *    Set the image type for I,P and SP pictures (not B!)
  ************************************************************************
  */
-void SetImgType(void)
+static void SetImgType(void)
 {
   int intra_refresh = (params->intra_period == 0) ? (IMG_NUMBER == 0) : (( ( img->frm_number - img->lastIntraNumber) % params->intra_period ) == 0);
   int idr_refresh;
diff --git a/lencod/src/loopFilter.c b/lencod/src/loopFilter.c
index d4adbda..0473c9e 100644
--- a/lencod/src/loopFilter.c
+++ b/lencod/src/loopFilter.c
@@ -292,12 +292,12 @@ void GetStrengthNormal(byte Strength[MB_BLOCK_SIZE],ImageParameters *img,int MbQ
 
     if (!ANY_INTRA)
     {
-      list0_refPicIdArr = enc_picture->ref_pic_id[LIST_0];
-      list1_refPicIdArr = enc_picture->ref_pic_id[LIST_1];
-      list0_mv = enc_picture->mv[LIST_0];
-      list1_mv = enc_picture->mv[LIST_1];
-      list0_refIdxArr = enc_picture->ref_idx[LIST_0];
-      list1_refIdxArr = enc_picture->ref_idx[LIST_1];
+      list0_refPicIdArr = enc_picture->motion.ref_pic_id[LIST_0];
+      list1_refPicIdArr = enc_picture->motion.ref_pic_id[LIST_1];
+      list0_mv = enc_picture->motion.mv[LIST_0];
+      list1_mv = enc_picture->motion.mv[LIST_1];
+      list0_refIdxArr = enc_picture->motion.ref_idx[LIST_0];
+      list1_refIdxArr = enc_picture->motion.ref_idx[LIST_1];
  
       get_mb_block_pos (MbQAddr, &mb_x, &mb_y);
       mb_x <<= 2;
@@ -413,12 +413,12 @@ void GetStrengthMBAff(byte Strength[16],ImageParameters *img,int MbQAddr,int dir
   int *mb_size = img->mb_size[IS_LUMA];
 
   MbQ = &(img->mb_data[MbQAddr]);
-  list0_mv = enc_picture->mv[LIST_0];
-  list1_mv = enc_picture->mv[LIST_1];
-  list0_refIdxArr = enc_picture->ref_idx[LIST_0];
-  list1_refIdxArr = enc_picture->ref_idx[LIST_1];
-  list0_refPicIdArr = enc_picture->ref_pic_id[LIST_0];
-  list1_refPicIdArr = enc_picture->ref_pic_id[LIST_1];
+  list0_mv = enc_picture->motion.mv[LIST_0];
+  list1_mv = enc_picture->motion.mv[LIST_1];
+  list0_refIdxArr = enc_picture->motion.ref_idx[LIST_0];
+  list1_refIdxArr = enc_picture->motion.ref_idx[LIST_1];
+  list0_refPicIdArr = enc_picture->motion.ref_pic_id[LIST_0];
+  list1_refPicIdArr = enc_picture->motion.ref_pic_id[LIST_1];
  
   for( idx=0 ; idx<16 ; idx++ )
   {
diff --git a/lencod/src/macroblock.c b/lencod/src/macroblock.c
index bb9cd98..eddaa0d 100644
--- a/lencod/src/macroblock.c
+++ b/lencod/src/macroblock.c
@@ -25,6 +25,7 @@
 #include <math.h>
 
 #include "global.h"
+#include "enc_statistics.h"
 
 #include "elements.h"
 #include "macroblock.h"
@@ -39,6 +40,7 @@
 #include "transform8x8.h"
 #include "transform.h"
 #include "me_fullsearch.h"
+#include "me_fullfast.h"
 #include "symbol.h"
 #include "rdo_quant.h"
 
@@ -48,11 +50,32 @@
 #define TRACE_SE(trace,str)
 #endif
 
-extern const byte QP_SCALE_CR[52] ;
+const byte QP_SCALE_CR[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
+};
 
-//Rate control
-extern int delta_qp_mbaff[2][2],delta_qp_mbaff[2][2];
-extern int qp_mbaff[2][2],qp_mbaff[2][2];
+static const int block8x8_idx[3][4][4] = 
+{
+  { {0, 1, 0, 0},
+  {2, 3, 0, 0},
+  {0, 0, 0, 0},
+  {0, 0, 0, 0},
+  },
+  { {0, 1, 0, 0},
+  {0, 1, 0, 0},
+  {2, 3, 0, 0},
+  {2, 3, 0, 0},
+  },
+  { {0, 0, 1, 1},
+  {0, 0, 1, 1},
+  {2, 2, 3, 3},
+  {2, 2, 3, 3}
+  }
+};
 
 static int  slice_too_big(int rlc_bits);
 
@@ -63,14 +86,10 @@ static int  writeCBPandDquant        (Macroblock* currMB);
 
 extern int *mvbits;
 
-extern int QP2QUANT[40];
-extern int ver_offset[4][8][4];
-extern int hor_offset[4][8][4];
-
 static int diff  [16];
 static int diff64[64];
 
-static const unsigned char subblk_offset_x[3][8][4] =
+const unsigned char subblk_offset_x[3][8][4] =
 {
   {
     {0, 4, 0, 4},
@@ -104,7 +123,7 @@ static const unsigned char subblk_offset_x[3][8][4] =
   }
 };
 
-static const unsigned char subblk_offset_y[3][8][4] =
+const unsigned char subblk_offset_y[3][8][4] =
 {
   {
     {0, 0, 4, 4},
@@ -166,13 +185,20 @@ void set_MB_parameters (int mb_addr)
   {
     if (img->mb_data[mb_addr].mb_field)
     {
-      pCurImg    = (mb_addr & 0x01) ? imgY_org_bot  : imgY_org_top;
+      pCurImg    = (mb_addr & 0x01) ? img_org_bot[0]  : img_org_top[0];
       pImgOrg[0] = pCurImg;
       if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
       {
-        imgUV_org  = (mb_addr & 0x01) ? imgUV_org_bot : imgUV_org_top;
-        pImgOrg[1] = imgUV_org[0];
-        pImgOrg[2] = imgUV_org[1];
+        if (mb_addr & 0x01)
+        {
+          pImgOrg[1] = img_org_bot[1];
+          pImgOrg[2] = img_org_bot[2];
+        }
+        else
+        {
+          pImgOrg[1] = img_org_top[1];
+          pImgOrg[2] = img_org_top[2];
+        }
       }
 
       img->opix_y   = (img->mb_y >> 1 ) << 4;
@@ -180,14 +206,15 @@ void set_MB_parameters (int mb_addr)
     }
     else
     {
-      pCurImg    = imgY_org_frm;      
-      pImgOrg[0] = imgY_org_frm;
+      pCurImg    = img_org_frm[0];      
+      pImgOrg[0] = img_org_frm[0];
+
       if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
       {
-        imgUV_org  = imgUV_org_frm;
-        pImgOrg[1] = imgUV_org_frm[0];
-        pImgOrg[2] = imgUV_org_frm[1];
+        pImgOrg[1] = img_org_frm[1];
+        pImgOrg[2] = img_org_frm[2];
       }
+
       img->opix_y   = img->block_y << 2;
       img->mb_data[mb_addr].list_offset = 0;
     }
@@ -244,12 +271,12 @@ void proceed2nextMacroblock(Macroblock *currMB)
 
     if ((currMB->cbp&15) != 0)
     {
-      ++stats->mode_use_transform[currMB->luma_transform_size_8x8_flag][img->type][currMB->mb_type];
+      ++stats->mode_use_transform[img->type][currMB->mb_type][currMB->luma_transform_size_8x8_flag];
     }
   }
 
   ++stats->mode_use[img->type][currMB->mb_type];
-  stats->bit_use_mode[img->type][currMB->mb_type]+= bitCount[BITS_INTER_MB];
+  stats->bit_use_mode[img->type][currMB->mb_type] += bitCount[BITS_INTER_MB];
 
   if (img->type != I_SLICE)
   {
@@ -265,45 +292,49 @@ void proceed2nextMacroblock(Macroblock *currMB)
         if (currMB->b8mode[i]==4)
         {
           if ((currMB->luma_transform_size_8x8_flag && (currMB->cbp&15) != 0) || params->Transform8x8Mode == 2)
-            ++stats->mode_use_transform[1][img->type][4];
+            ++stats->mode_use_transform[img->type][4][1];
           else
-            ++stats->mode_use_transform[0][img->type][4];
+            ++stats->mode_use_transform[img->type][4][0];
         }
       }
     }
     else if (currMB->mb_type >= 0 && currMB->mb_type <=3 && ((currMB->cbp&15) != 0))
     {
-      ++stats->mode_use_transform[currMB->luma_transform_size_8x8_flag][img->type][currMB->mb_type];
+      ++stats->mode_use_transform[img->type][currMB->mb_type][currMB->luma_transform_size_8x8_flag];
     }
   }
 
   // Statistics
-  if ((img->type == P_SLICE)||(img->type==SP_SLICE) )
+  if ((img->type == P_SLICE) || (img->type==SP_SLICE) )
   {
     ++stats->quant0;
     stats->quant1 += currMB->qp;      // to find average quant for inter frames
   }
 }
 
+void set_chroma_qp(ImageParameters *img, Macroblock* currMB)
+{
+  int i;
+  for (i=0; i<2; i++)
+  {
+    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + img->chroma_qp_offset[i] );
+    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
+    currMB->qp_scaled[i + 1] = currMB->qpc[i] + img->bitdepth_chroma_qp_scale;
+  }  
+}
+
 /*!
 ************************************************************************
 * \brief
 *    updates chroma QP according to luma QP and bit depth
 ************************************************************************
 */
-void update_qp(Macroblock *currMB)
+void update_qp(ImageParameters *img, Macroblock *currMB)
 {
-  int i;
-  for (i=0; i<2; i++)
-  {
-    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + img->chroma_qp_offset[i] );
-    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
-  }
-  currMB->qp_scaled[0] = currMB->qp + img->bitdepth_luma_qp_scale - MIN_QP;
-  currMB->qp_scaled[1] = currMB->qpc[0] + img->bitdepth_chroma_qp_scale;
-  currMB->qp_scaled[2] = currMB->qpc[1] + img->bitdepth_chroma_qp_scale;
+  currMB->qp_scaled[0] = currMB->qp + img->bitdepth_luma_qp_scale;
+  set_chroma_qp(img, currMB);
 
-  select_dct(currMB);
+  select_dct(img, currMB);
 }
 
 /*!
@@ -326,10 +357,10 @@ void reset_macroblock(Macroblock *currMB, int prev_mb)
   {
     for (j=img->block_y; j < img->block_y + BLOCK_MULTIPLE; j++)
     {
-      memset(&enc_picture->ref_idx[l][j][img->block_x], -1, BLOCK_MULTIPLE * sizeof(char));
-      memset(enc_picture->mv [l][j][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
+      memset(&enc_picture->motion.ref_idx[l][j][img->block_x], -1, BLOCK_MULTIPLE * sizeof(char));
+      memset(enc_picture->motion.mv [l][j][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
       for (i=img->block_x; i < img->block_x + BLOCK_MULTIPLE; i++)
-        enc_picture->ref_pic_id[l][j][i]= -1;
+        enc_picture->motion.ref_pic_id[l][j][i]= -1;
     }
   }
 
@@ -394,7 +425,7 @@ void reset_macroblock(Macroblock *currMB, int prev_mb)
  */
 void start_macroblock(Macroblock **currMB, int mb_addr, int mb_field)
 {
-  int i;
+  int i, mb_qp;
   int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
   Slice *curr_slice = img->currentSlice;
   DataPartition *dataPart;
@@ -407,7 +438,7 @@ void start_macroblock(Macroblock **currMB, int mb_addr, int mb_field)
 
   (*currMB)->mb_field = mb_field;
 
-  enc_picture->mb_field[mb_addr] = mb_field;
+  enc_picture->motion.mb_field[mb_addr] = mb_field;
   (*currMB)->is_field_mode = (img->field_picture || ( img->MbaffFrameFlag && (*currMB)->mb_field));
 
   set_MB_parameters (mb_addr);
@@ -451,60 +482,31 @@ void start_macroblock(Macroblock **currMB, int mb_addr, int mb_field)
   // Initialize delta qp change from last macroblock. Feature may be used for future rate control
   // Rate control
   (*currMB)->qpsp       = img->qpsp;
-  if(params->RCEnable)
-    rc_handle_mb( prev_mb, *currMB, curr_slice );
+
+  if (prev_mb > -1 && (img->mb_data[prev_mb].slice_nr == img->current_slice_nr))
+  {
+    (*currMB)->prev_qp  = img->mb_data[prev_mb].qp;
+    (*currMB)->prev_dqp = img->mb_data[prev_mb].delta_qp;
+  }
   else
   {
-    Slice* currSlice = img->currentSlice;
-    int new_qp = img->qp;
-
-    if (prev_mb > -1)
-    {
-      (*currMB)->prev_qp = img->mb_data[prev_mb].qp;
-      (*currMB)->prev_dqp = (img->mb_data[prev_mb].slice_nr == img->current_slice_nr) ? img->mb_data[prev_mb].delta_qp : 0;
-    }
-    else
-    {
-      (*currMB)->prev_qp = currSlice->qp;
-      (*currMB)->prev_dqp = 0;
-    }
+    (*currMB)->prev_qp  = curr_slice->qp;
+    (*currMB)->prev_dqp = 0;
+  }
 
-    if (prev_mb < 0) //first macroblock (of slice)
-    {
-      (*currMB)->qp       = img->qp;
-      (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;      
-    }
-    else
-    {
-      if (!((params->MbInterlace) && img->bot_MB)) //top macroblock
-      {
-        if (img->mb_data[prev_mb].prev_cbp == 1)
-        {
-          (*currMB)->qp       = img->qp;
-          (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;      
-        }
-        else
-        {
-          (*currMB)->qp = img->mb_data[prev_mb].prev_qp;
-          (*currMB)->delta_qp = (*currMB)->qp - img->mb_data[prev_mb].qp;
-          img->qp = (*currMB)->qp;
-        }
-      }
-      else //bottom macroblock
-      {
-        (*currMB)->qp       = img->qp;
-        (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;    
-      }
-    }
+  if(params->RCEnable)
+    mb_qp = rc_handle_mb( prev_mb, *currMB, curr_slice );
+  else
+  {
+    mb_qp = img->qp;
 
-    (*currMB)->qp       = img->qp = new_qp;
-    (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;      
   }
 
-  delta_qp_mbaff[(*currMB)->mb_field][img->bot_MB] = (*currMB)->delta_qp;
-  qp_mbaff      [(*currMB)->mb_field][img->bot_MB] = (*currMB)->qp;
+  mb_qp = iClip3(-img->bitdepth_luma_qp_scale, 51, mb_qp);
+  (*currMB)->qp       = img->qp = mb_qp;
+  (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;
 
-  update_qp (*currMB);
+  update_qp (img, *currMB);
 
   // deblocking filter parameter
   if (active_pps->deblocking_filter_control_present_flag)
@@ -850,6 +852,7 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
   //set transform size
   int    need_8x8_transform = currMB->luma_transform_size_8x8_flag;
   int    uv, nonzerocr[3]={0,0,0};  
+  short bipred_me = currMB->bipred_me[block8x8];
   coeff_cost_cr[1] = coeff_cost_cr[2] = 0;
 
   //===== loop over 4x4 blocks =====
@@ -857,10 +860,10 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
   {
     if (((p_dir == 0 || p_dir == 2 )&& l0_mode < 5) || ((p_dir == 1 || p_dir == 2 ) && l1_mode < 5))
     {
-      LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
+      LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx, bipred_me); 
 
       //===== compute prediction residual ======            
-      ComputeResidue (pCurImg, img->mpr[0], img->m7[0], mb_y, mb_x, img->opix_y, img->opix_x + mb_x, 8, 8);
+      ComputeResidue (pCurImg, img->mb_pred[0], img->mb_ores[0], mb_y, mb_x, img->opix_y, img->opix_x + mb_x, 8, 8);
     }
 
     for (byy=0, block_y=mb_y; block_y<mb_y+8; byy+=4, block_y+=4)
@@ -873,21 +876,21 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
         //===== prediction of 4x4 block =====
         if (!(((p_dir == 0 || p_dir == 2 )&& l0_mode < 5) || ((p_dir == 1 || p_dir == 2 ) && l1_mode < 5)))
         {
-          LumaPrediction (currMB, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
+          LumaPrediction (currMB, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx, bipred_me);
 
           //===== compute prediction residual ======            
-          ComputeResidue(pCurImg, img->mpr[0], img->m7[0], block_y, block_x, img->opix_y, pic_pix_x, 4, 4);
+          ComputeResidue(pCurImg, img->mb_pred[0], img->mb_ores[0], block_y, block_x, img->opix_y, pic_pix_x, 4, 4);
         }
 
         if (img->P444_joined)
         {
-          for (uv=0; uv<2; uv++)
+          for (uv = PLANE_U; uv <= PLANE_V; uv++)
           {
-            select_plane((ColorPlane) (uv + 1));
-            ChromaPrediction (currMB, uv, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
+            select_plane((ColorPlane) (uv));
+            ChromaPrediction (currMB, uv - 1, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx, bipred_me);
             
             //===== compute prediction residual ======            
-            ComputeResidue(imgUV_org[uv], img->mpr[uv+1], img->m7[uv+1], block_y, block_x, img->opix_y, pic_pix_x, 4, 4);
+            ComputeResidue(pImgOrg[uv], img->mb_pred[uv], img->mb_ores[uv], block_y, block_x, img->opix_y, pic_pix_x, 4, 4);
           }
           select_plane(PLANE_Y);
         }
@@ -897,7 +900,6 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
           ((currMB->qp_scaled[0])==0 && img->lossless_qpprime_flag==1) )
         {
           //===== DCT, Quantization, inverse Quantization, IDCT, Reconstruction =====
-          //select_dct(currMB);
           nonzero = pDCT_4x4 (currMB, PLANE_Y, block_x, block_y, &coeff_cost, 0);
 
           if (nonzero)
@@ -944,20 +946,20 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
         cbp_blk_mask = (block_x>>2) + block_y;
 
         //===== prediction of 4x4 block =====
-        LumaPrediction (currMB, block_x, block_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
+        LumaPrediction (currMB, block_x, block_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx, bipred_me);
 
         //===== compute prediction residual ======            
-        ComputeResidue (pCurImg, img->mpr[0], img->m7[0], block_y, block_x, img->opix_y, pic_pix_x, 8, 8);
+        ComputeResidue (pCurImg, img->mb_pred[0], img->mb_ores[0], block_y, block_x, img->opix_y, pic_pix_x, 8, 8);
 
         if (img->P444_joined) 
         {
-          for (uv=0; uv<2; uv++)
+          for (uv = PLANE_U; uv <= PLANE_V; uv++)
           {
-            select_plane((ColorPlane) (uv + 1));
-            ChromaPrediction (currMB, uv, block_x, block_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
+            select_plane((ColorPlane) uv);
+            ChromaPrediction (currMB, uv - 1, block_x, block_y, 8, 8, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx, bipred_me);
 
             //===== compute prediction residual ======            
-            ComputeResidue (imgUV_org[uv], img->mpr[uv + 1], img->m7[uv + 1], block_y, block_x, img->opix_y, pic_pix_x, 8, 8);
+            ComputeResidue (pImgOrg[uv], img->mb_pred[uv], img->mb_ores[uv], block_y, block_x, img->opix_y, pic_pix_x, 8, 8);
           }
           select_plane(PLANE_Y);
         }
@@ -1027,7 +1029,7 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
     memset( img->cofAC[block8x8][0][0], 0, 4 * 2 * 65 * sizeof(int));
     
     for (j=mb_y; j<mb_y+8; j++)
-      memcpy(&enc_picture->imgY[img->pix_y + j][img->pix_x + mb_x], &img->mpr[0][j][mb_x], 2 * BLOCK_SIZE * sizeof(imgpel));
+      memcpy(&enc_picture->imgY[img->pix_y + j][img->pix_x + mb_x], &img->mb_pred[0][j][mb_x], 2 * BLOCK_SIZE * sizeof(imgpel));
 
     if (img->type==SP_SLICE)
     {
@@ -1051,7 +1053,7 @@ int LumaResidualCoding8x8 ( Macroblock* currMB, //!< Current Macroblock to be co
         memset( img->cofAC[block8x8 + 4 * uv][0][0], 0, 4 * 2 * 65 * sizeof(int));
 
         for (j=mb_y; j<mb_y+8; j++)
-          memcpy(&enc_picture->imgUV[uv - 1][img->pix_y + j][img->pix_x + mb_x], &img->mpr[uv][j][mb_x], 2 * BLOCK_SIZE * sizeof(imgpel));
+          memcpy(&enc_picture->imgUV[uv - 1][img->pix_y + j][img->pix_x + mb_x], &img->mb_pred[uv][j][mb_x], 2 * BLOCK_SIZE * sizeof(imgpel));
       }
     }
   }
@@ -1076,7 +1078,7 @@ void SetModesAndRefframe (Macroblock* currMB, int b8, short* p_dir, int list_mod
 
   if (img->type!=B_SLICE)
   {
-    list_ref_idx[0] = enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x+i];
+    list_ref_idx[0] = enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x+i];
     list_ref_idx[1] = 0;
     list_mode[0] = currMB->b8mode[b8];
     list_mode[1] = 0;
@@ -1092,7 +1094,7 @@ void SetModesAndRefframe (Macroblock* currMB, int b8, short* p_dir, int list_mod
     }
     else if (currMB->b8pdir[b8]==0)
     {
-      list_ref_idx[0] = enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x+i];
+      list_ref_idx[0] = enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x+i];
       list_ref_idx[1] = 0;
       list_mode[0] = currMB->b8mode[b8];
       list_mode[1] = 0;
@@ -1100,14 +1102,14 @@ void SetModesAndRefframe (Macroblock* currMB, int b8, short* p_dir, int list_mod
     else if (currMB->b8pdir[b8]==1)
     {
       list_ref_idx[0] = 0;
-      list_ref_idx[1] = enc_picture->ref_idx[LIST_1][img->block_y+j][img->block_x+i];
+      list_ref_idx[1] = enc_picture->motion.ref_idx[LIST_1][img->block_y+j][img->block_x+i];
       list_mode[0] = 0;
       list_mode[1] = currMB->b8mode[b8];
     }
     else
     {
-      list_ref_idx[0] = enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x+i];
-      list_ref_idx[1] = enc_picture->ref_idx[LIST_1][img->block_y+j][img->block_x+i];
+      list_ref_idx[0] = enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x+i];
+      list_ref_idx[1] = enc_picture->motion.ref_idx[LIST_1][img->block_y+j][img->block_x+i];
       list_mode[0] = currMB->b8mode[b8];
       list_mode[1] = currMB->b8mode[b8];
     }
@@ -1128,7 +1130,7 @@ void LumaResidualCoding (Macroblock *currMB)
   short list_ref_idx[2];
   short p_dir;
   int sum_cnt_nonz[3] = {0 ,0, 0};
-  //imgpel (*curr_mpr)[16] = img->mpr[0];
+  //imgpel (*mb_pred)[16] = img->mb_pred[0];
 
   currMB->cbp     = 0;
   currMB->cbp_blk = 0;
@@ -1157,7 +1159,7 @@ void LumaResidualCoding (Macroblock *currMB)
     currMB->cbp     &= 0xfffff0 ;
     currMB->cbp_blk &= 0xff0000 ;
     for (j=0; j < MB_BLOCK_SIZE; j++)
-      memcpy(&enc_picture->imgY[img->pix_y+j][img->pix_x], img->mpr[0][j], MB_BLOCK_SIZE * sizeof (imgpel));
+      memcpy(&enc_picture->imgY[img->pix_y+j][img->pix_x], img->mb_pred[0][j], MB_BLOCK_SIZE * sizeof (imgpel));
         
     memset( img->cofAC[0][0][0], 0, 4 * 4 * 2 * 65 * sizeof(int));
 
@@ -1184,7 +1186,7 @@ void LumaResidualCoding (Macroblock *currMB)
         cmp_cbp[uv] &= 0xfffff0 ;
         cur_cbp_blk[uv] &= 0xff0000 ;
         for (j=0; j < MB_BLOCK_SIZE; j++)
-          memcpy(&enc_picture->p_img[uv][img->pix_y+j][img->pix_x], img->mpr[uv][j], MB_BLOCK_SIZE * sizeof (imgpel));
+          memcpy(&enc_picture->p_img[uv][img->pix_y+j][img->pix_x], img->mb_pred[uv][j], MB_BLOCK_SIZE * sizeof (imgpel));
 
         memset( img->cofAC[4 * uv][0][0], 0, 4 * 4 * 2 * 65 * sizeof(int));
       }
@@ -1209,7 +1211,8 @@ int TransformDecision (Macroblock *currMB, int block_check, int *cost)
   int    num_blks;
   int    cost8x8=0, cost4x4=0;
   int    *diff_ptr;
-  imgpel (*curr_mpr)[16] = img->mpr[0];
+  short bipred_me;
+  imgpel (*mb_pred)[16] = img->mb_pred[0];
 
   if(block_check==-1)
   {
@@ -1225,12 +1228,12 @@ int TransformDecision (Macroblock *currMB, int block_check, int *cost)
   for (; block8x8<num_blks; block8x8++)
   {
     SetModesAndRefframe (currMB, block8x8, &p_dir, list_mode, list_ref_idx);
-
+    bipred_me = currMB->bipred_me[block8x8]; 
     mb_y = (block8x8 >> 1) << 3;
     mb_x = (block8x8 & 0x01) << 3;
         
     //===== prediction of 8x8 block =====
-    LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1]);
+    LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);
 
     //===== loop over 4x4 blocks =====
     for (k=0, block_y=mb_y; block_y<mb_y+8; block_y+=4)
@@ -1242,7 +1245,7 @@ int TransformDecision (Macroblock *currMB, int block_check, int *cost)
         for (j=block_y; j<block_y + 4; j++)
         {
           for (i = block_x; i < block_x + 4; i++, k++)
-            diff64[k] = pCurImg[img->opix_y+j][img->opix_x + i] - curr_mpr[j][i];
+            diff64[k] = pCurImg[img->opix_y+j][img->opix_x + i] - mb_pred[j][i];
         }
         cost4x4 += distortion4x4 (diff_ptr);
       }
@@ -1272,43 +1275,27 @@ int TransformDecision (Macroblock *currMB, int block_check, int *cost)
 void ChromaResidualCoding (Macroblock *currMB)
 {
   int chroma_cbp;
-  static const int block8x8_idx[3][4][4] =     //ADD-VG-15052004
-  {
-    { {0, 1, 0, 0},
-      {2, 3, 0, 0},
-      {0, 0, 0, 0},
-      {0, 0, 0, 0},
-    },
-    { {0, 1, 0, 0},
-      {0, 1, 0, 0},
-      {2, 3, 0, 0},
-      {2, 3, 0, 0},
-    },
-    { {0, 0, 1, 1},
-      {0, 0, 1, 1},
-      {2, 2, 3, 3},
-      {2, 2, 3, 3}
-    }
-  };
   static int   uv, block8, block_y, block_x, j, i;
   static int   list_mode[2];
   static short p_dir, list_ref_idx[2];
   int   skipped = (currMB->mb_type == 0 && (img->type == P_SLICE || img->type == SP_SLICE));
   int   yuv = img->yuv_format - 1; 
-  imgpel (*curr_mpr)[16] = NULL;
+  short bipred_me;
+  imgpel (*mb_pred)[16] = NULL;
   
   for (chroma_cbp = 0, uv=0; uv<2; uv++)
   {
-    curr_mpr = img->mpr[ uv + 1];
+    mb_pred = img->mb_pred[ uv + 1];
     //===== prediction of chrominance blocks ===d==
     block8 = 0;
     for (block_y=0; block_y < img->mb_cr_size_y; block_y+=4)
     for (block_x=0; block_x < img->mb_cr_size_x; block_x+=4)
     {
       block8 = block8x8_idx[yuv][block_y>>2][block_x>>2];
+      bipred_me = currMB->bipred_me[block8];
       SetModesAndRefframe (currMB, block8, &p_dir, list_mode, list_ref_idx);
 
-      ChromaPrediction4x4 (currMB, uv, block_x, block_y, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1]);
+      ChromaPrediction4x4 (currMB, uv, block_x, block_y, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);
       //ChromaPrediction    (currMB, uv, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
     }
 
@@ -1316,24 +1303,26 @@ void ChromaResidualCoding (Macroblock *currMB)
     if (img->NoResidueDirect)
     {
       for (j=0; j<img->mb_cr_size_y; j++)
-        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], curr_mpr[j], img->mb_cr_size_x * sizeof(imgpel));
+        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
     }
     else if (skipped && img->type==SP_SLICE)
     {
       for (j=0; j<img->mb_cr_size_y; j++)
-        memset(img->m7[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
+        memset(img->mb_ores[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
+      for (j=0; j<img->mb_cr_size_y; j++)
+        memset(img->mb_rres[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
     }
     else if (skipped)
     {
       for (j=0; j<img->mb_cr_size_y; j++)
-        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], curr_mpr[j], img->mb_cr_size_x * sizeof(imgpel));
+        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
     }
     else
     {
       for (j=0; j<img->mb_cr_size_y; j++)
         for (i=0; i<img->mb_cr_size_x; i++)
         {
-          img->m7[uv + 1][j][i] = imgUV_org[uv][img->opix_c_y+j][img->opix_c_x+i] - curr_mpr[j][i];
+          img->mb_ores[uv + 1][j][i] = pImgOrg[uv + 1][img->opix_c_y+j][img->opix_c_x+i] - mb_pred[j][i];
         }
     }
 
@@ -1343,9 +1332,9 @@ void ChromaResidualCoding (Macroblock *currMB)
     if (skipped && img->type==SP_SLICE)
     {
       if(si_frame_indicator || sp2_frame_indicator)
-        chroma_cbp=dct_chroma_sp2(currMB, uv,chroma_cbp);
+        chroma_cbp = dct_chroma_sp2(currMB, uv,chroma_cbp);
       else
-        chroma_cbp=dct_chroma_sp(currMB, uv,chroma_cbp);
+        chroma_cbp = dct_chroma_sp(currMB, uv,chroma_cbp);
     }
     else
     {
@@ -1443,10 +1432,10 @@ void IntraChromaRDDecision (Macroblock *currMB, RD_PARAMS enc_mb)
       continue;
 
     cost = 0;
-    for (uv=0; uv<2; uv++)
+    for (uv = 1; uv < 3; uv++)
     {
-      image = imgUV_org[uv];
-      curr_mpr_16x16 = img->mpr_16x16[uv + 1];
+      image = pImgOrg[uv];
+      curr_mpr_16x16 = img->mpr_16x16[uv];
       for (block_y=0; block_y<cr_MB_y; block_y+=4)
       {
         for (block_x=0; block_x<cr_MB_x; block_x+=4)
@@ -1493,7 +1482,7 @@ int ZeroRef (Macroblock* currMB)
   {
     for (i=img->block_x; i<img->block_x + BLOCK_MULTIPLE; i++)
     {
-      if (enc_picture->ref_idx[LIST_0][j][i]!=0)
+      if (enc_picture->motion.ref_idx[LIST_0][j][i]!=0)
         return 0;
     }
   }
@@ -1916,6 +1905,7 @@ int writeMBLayer (Macroblock *currMB, int rdopt, int *coeff_rate)
       arienco_start_encoding(eep, dataPart->bitstream->streamBuffer, &(dataPart->bitstream->byte_pos));
       reset_pic_bin_count();
     }
+
     if (dataPart->bitstream->bits_to_go < 8)
     {
       // This will only happen in the CAVLC case, CABAC is already padded
@@ -1961,7 +1951,7 @@ int writeMBLayer (Macroblock *currMB, int rdopt, int *coeff_rate)
             no_bits += se.len;
             se.bitpattern = enc_picture->imgUV[uv][j][i];
             se.value1 = se.bitpattern;
-            bitCount[BITS_COEFF_UV_MB]+=se.len;
+            bitCount[BITS_COEFF_UV_MB] += se.len;
 #if TRACE
             snprintf(se.tracestring, TRACESTRING_SIZE, "pcm_sample_chroma (%s) (%d %d) = %d", uv?"v":"u", j,i,se.bitpattern);
 #endif
@@ -2167,21 +2157,14 @@ void write_one_macroblock (Macroblock* currMB, int eos_bit, Boolean prev_recode_
   }
 
   //--- set total bit-counter ---
-  if(img->P444_joined)
-    bitCount[BITS_TOTAL_MB] = bitCount[BITS_MB_MODE       ]  
-                            + bitCount[BITS_COEFF_Y_MB    ]
-                            + bitCount[BITS_INTER_MB      ] 
-                            + bitCount[BITS_CBP_MB        ]
-                            + bitCount[BITS_DELTA_QUANT_MB] 
-                            + bitCount[BITS_COEFF_CB_MB   ] 
-                            + bitCount[BITS_COEFF_CR_MB   ];
-  else
-    bitCount[BITS_TOTAL_MB] = bitCount[BITS_MB_MODE       ]  
-                            + bitCount[BITS_COEFF_Y_MB    ]
-                            + bitCount[BITS_INTER_MB      ] 
-                            + bitCount[BITS_CBP_MB        ]
-                            + bitCount[BITS_DELTA_QUANT_MB] 
-                            + bitCount[BITS_COEFF_UV_MB   ];
+  bitCount[BITS_TOTAL_MB] = bitCount[BITS_MB_MODE       ]  
+                          + bitCount[BITS_COEFF_Y_MB    ]
+                          + bitCount[BITS_INTER_MB      ] 
+                          + bitCount[BITS_CBP_MB        ]
+                          + bitCount[BITS_DELTA_QUANT_MB] 
+                          + bitCount[BITS_COEFF_UV_MB   ]
+                          + bitCount[BITS_COEFF_CB_MB   ] 
+                          + bitCount[BITS_COEFF_CR_MB   ];
 
   if ( params->RCEnable )
     rc_update_mb_stats( currMB, bitCount );  
@@ -2247,7 +2230,9 @@ int writeMotionVector8x8 (Macroblock *currMB,
                           int  j1,
                           int  refframe,
                           int  list_idx,
-                          int  mv_mode)
+                          int  mv_mode,
+                          short bipred_me
+                          )
 {
   int            i, j, k, l, m;
   int            curr_mvd;
@@ -2265,8 +2250,8 @@ int writeMotionVector8x8 (Macroblock *currMB,
   short******    all_mv     = img->all_mv;
   short******    pred_mv    = img->pred_mv;  
 
-  if (currMB->bi_pred_me && currMB->b8pdir[0]==2 && mv_mode == 1 && refindex == 0)
-    all_mv = currMB->bi_pred_me == 1? img->bipred_mv1 : img->bipred_mv2 ;
+  if (bipred_me && is_bipred_enabled(mv_mode) && refindex == 0)
+    all_mv = img->bipred_mv[bipred_me - 1]; 
 
   for (j = j0; j < j1; j += step_v)
   {
@@ -2331,7 +2316,7 @@ int writeMotionInfo2NAL (Macroblock* currMB)
     {
       for (j0 = 0; j0 < 4; j0 += step_v0)
       {
-        cref_idx = &enc_picture->ref_idx[LIST_0][img->block_y + j0][img->block_x];
+        cref_idx = &enc_picture->motion.ref_idx[LIST_0][img->block_y + j0][img->block_x];
         for (i0 = 0; i0 < 4; i0 += step_h0)
         {
           k = j0 + (i0 >> 1);
@@ -2344,7 +2329,7 @@ int writeMotionInfo2NAL (Macroblock* currMB)
 
       for (j0 = 0; j0 < 4; j0 += step_v0)
       {        
-        cref_idx = &enc_picture->ref_idx[LIST_1][img->block_y + j0][img->block_x];
+        cref_idx = &enc_picture->motion.ref_idx[LIST_1][img->block_y + j0][img->block_x];
         for (i0 = 0; i0 < 4; i0 += step_h0)
         {
           k = j0 + (i0 >> 1);
@@ -2362,13 +2347,13 @@ int writeMotionInfo2NAL (Macroblock* currMB)
   {
     for (j0=0; j0<4; j0+=step_v0)
     {
-      cref_idx = &enc_picture->ref_idx[LIST_0][img->block_y + j0][img->block_x];
+      cref_idx = &enc_picture->motion.ref_idx[LIST_0][img->block_y + j0][img->block_x];
       for (i0=0; i0<4; i0+=step_h0)
       {
         k=j0+(i0 >> 1);
         if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)//has forward vector
         {
-          no_bits  += writeMotionVector8x8 (currMB, i0, j0, i0 + step_h0, j0 + step_v0, cref_idx[i0], LIST_0, currMB->b8mode[k]);
+          no_bits  += writeMotionVector8x8 (currMB, i0, j0, i0 + step_h0, j0 + step_v0, cref_idx[i0], LIST_0, currMB->b8mode[k], currMB->bipred_me[k]);
         }
       }
     }
@@ -2380,13 +2365,13 @@ int writeMotionInfo2NAL (Macroblock* currMB)
   {
     for (j0=0; j0<4; j0+=step_v0)
     {
-      cref_idx = &enc_picture->ref_idx[LIST_1][img->block_y + j0][img->block_x];
+      cref_idx = &enc_picture->motion.ref_idx[LIST_1][img->block_y + j0][img->block_x];
       for (i0=0; i0<4; i0+=step_h0)
       {
         k=j0+(i0 >> 1);
         if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)//has backward vector
         {          
-          no_bits  += writeMotionVector8x8 (currMB, i0, j0, i0+step_h0, j0+step_v0, cref_idx[i0], LIST_1, currMB->b8mode[k]);
+          no_bits  += writeMotionVector8x8 (currMB, i0, j0, i0+step_h0, j0+step_v0, cref_idx[i0], LIST_1, currMB->b8mode[k], currMB->bipred_me[k]);
         }
       }
     }
@@ -2578,7 +2563,7 @@ int writeCoeff4x4_CABAC (Macroblock* currMB, ColorPlane plane, int b8, int b4, i
   int level, run;
   int k;
   int pl_off=plane<<2;
-  int bits_coeff_mb=((plane==0)?(BITS_COEFF_Y_MB):((plane==1)?BITS_COEFF_CB_MB:BITS_COEFF_CR_MB));
+  int bits_coeff_mb = ((plane==0) ? (BITS_COEFF_Y_MB) : ((plane==1) ? BITS_COEFF_CB_MB : BITS_COEFF_CR_MB));
   int*  ACLevel = img->cofAC[b8+pl_off][b4][0];
   int*  ACRun   = img->cofAC[b8+pl_off][b4][1];
 
@@ -2633,7 +2618,7 @@ int writeCoeff8x8_CABAC (Macroblock* currMB, ColorPlane plane, int b8, int intra
   int   k;
 
   int pl_off=plane<<2;
-  int bits_coeff_mb=((plane==0)?(BITS_COEFF_Y_MB):((plane==1)?BITS_COEFF_CB_MB:BITS_COEFF_CR_MB));
+  int bits_coeff_mb = ((plane == 0) ? (BITS_COEFF_Y_MB) : ((plane == 1) ? BITS_COEFF_CB_MB : BITS_COEFF_CR_MB));
   int*  ACLevel = img->cofAC[b8+pl_off][0][0];
   int*  ACRun   = img->cofAC[b8+pl_off][0][1];
 
@@ -2810,7 +2795,7 @@ int writeCoeff16x16 (Macroblock* currMB, ColorPlane plane, int cbp)
   int*  ACLevel;
   int*  ACRun;
   int   data_type; 
-  int   bits_coeff_mb=((plane==0)?(BITS_COEFF_Y_MB):((plane==1)?(BITS_COEFF_CB_MB):(BITS_COEFF_CR_MB)));
+  int   bits_coeff_mb = ((plane == 0) ? (BITS_COEFF_Y_MB) : ((plane == 1) ? (BITS_COEFF_CB_MB) : (BITS_COEFF_CR_MB)));
 
   if (img->P444_joined)
   {
@@ -3750,16 +3735,16 @@ double find_sad_16x16_JM(Macroblock *currMB, int *intra_mode)
         current_intra_sad_2 = distortion_sad(pCurImg, curr_mpr_16x16[k]);
         if (img->P444_joined)
         {
-          current_intra_sad_2 += distortion_sad(imgUV_org[0], img->mpr_16x16[1][k]);
-          current_intra_sad_2 += distortion_sad(imgUV_org[1], img->mpr_16x16[2][k]);
+          current_intra_sad_2 += distortion_sad(pImgOrg[1], img->mpr_16x16[1][k]);
+          current_intra_sad_2 += distortion_sad(pImgOrg[2], img->mpr_16x16[2][k]);
         }
         break;
       case ERROR_SSE:
         current_intra_sad_2 = distortion_sse(pCurImg, curr_mpr_16x16[k]);
         if (img->P444_joined)
         {
-          current_intra_sad_2 += distortion_sse(imgUV_org[0], img->mpr_16x16[1][k]);
-          current_intra_sad_2 += distortion_sse(imgUV_org[1], img->mpr_16x16[2][k]);
+          current_intra_sad_2 += distortion_sse(pImgOrg[1], img->mpr_16x16[1][k]);
+          current_intra_sad_2 += distortion_sse(pImgOrg[2], img->mpr_16x16[2][k]);
         }
         break;
       case ERROR_SATD :
@@ -3767,8 +3752,8 @@ double find_sad_16x16_JM(Macroblock *currMB, int *intra_mode)
         current_intra_sad_2 = distortion_hadamard(pCurImg, curr_mpr_16x16[k]);
         if (img->P444_joined)
         {
-          current_intra_sad_2 += distortion_hadamard(imgUV_org[0], img->mpr_16x16[1][k]);
-          current_intra_sad_2 += distortion_hadamard(imgUV_org[1], img->mpr_16x16[2][k]);
+          current_intra_sad_2 += distortion_hadamard(pImgOrg[1], img->mpr_16x16[1][k]);
+          current_intra_sad_2 += distortion_hadamard(pImgOrg[2], img->mpr_16x16[2][k]);
         }
         break;
       }
@@ -3797,9 +3782,9 @@ void change_plane_JV( int nplane )
 {
   img->colour_plane_id = nplane;
   img->mb_data = img->mb_data_JV[nplane];
-  enc_picture = enc_frame_picture_JV[nplane];
-  pCurImg = imgY_org_frm_JV[nplane];
-  Co_located = Co_located_JV[nplane];
+  enc_picture  = enc_frame_picture_JV[nplane];
+  pCurImg      = img_org_frm[nplane];
+  Co_located   = Co_located_JV[nplane];
 }
 
 /*!
@@ -3819,7 +3804,8 @@ void make_frame_picture_JV()
     copy_storable_param_JV( nplane, enc_frame_picture[0], enc_frame_picture_JV[nplane] );
   }
 
-  for( uv=0; uv<2; uv++ ){
+  for( uv=0; uv<2; uv++ )
+  {
     for( line=0; line<img->height; line++ )
     {
       nsize = sizeof(imgpel) * img->width;
diff --git a/lencod/src/mb_access.c b/lencod/src/mb_access.c
index d90a43b..c054a5d 100644
--- a/lencod/src/mb_access.c
+++ b/lencod/src/mb_access.c
@@ -133,8 +133,8 @@ void get_mb_pos (int mb_addr, int mb_size[2], int *x, int*y)
  *    input x position
  * \param yN
  *    input y position
- * \param is_chroma
- *    0 if luma coding, 1 for chroma
+ * \param mb_size
+ *    Macroblock size in pixel (according to luma or chroma MB access)
  * \param pix
  *    returns position informations
  ************************************************************************
@@ -194,8 +194,8 @@ void getNonAffNeighbour(Macroblock *currMb, int xN, int yN, int mb_size[2], Pixe
  *    input x position
  * \param yN
  *    input y position
- * \param is_chroma
- *    0 if luma coding, 1 for chroma
+ * \param mb_size
+ *    Macroblock size in pixel (according to luma or chroma MB access)
  * \param pix
  *    returns position informations
  ************************************************************************
@@ -540,6 +540,8 @@ void getAffNeighbour(Macroblock *currMb, int xN, int yN, int mb_size[2], PixelPo
  *    input x block position
  * \param block_y
  *    input y block position
+ * \param mb_size
+ *    Macroblock size in pixel (according to luma or chroma MB access)
  * \param pix
  *    returns position informations
  ************************************************************************
diff --git a/lencod/src/mbuffer.c b/lencod/src/mbuffer.c
index 43656a5..ff5b9e3 100644
--- a/lencod/src/mbuffer.c
+++ b/lencod/src/mbuffer.c
@@ -111,10 +111,10 @@ int getDpbSize(void)
     size = 152064;
     break;
   case 11:
-    if (!IS_FREXT_PROFILE(active_sps->profile_idc)&&(active_sps->constrained_set3_flag == 0))
-      size = 345600;
-    else
+    if (!IS_FREXT_PROFILE(active_sps->profile_idc)&&(active_sps->constrained_set3_flag == 1))
       size = 152064;
+    else
+      size = 345600;
     break;
   case 12:
     size = 912384;
@@ -147,10 +147,7 @@ int getDpbSize(void)
     size = 12582912;
     break;
   case 42:
-    if( IS_FREXT_PROFILE(active_sps->profile_idc) )
-      size = 13369344;
-    else
-      size = 12582912;
+    size = 13369344;
     break;
   case 50:
     size = 42393600;
@@ -326,6 +323,20 @@ FrameStore* alloc_frame_store(void)
   return f;
 }
 
+void alloc_pic_motion(PicMotionParams *motion, int size_y, int size_x)
+{
+  get_mem3Dint64 (&(motion->ref_pic_id), 6, size_y, size_x);
+  get_mem3Dint64 (&(motion->ref_id),     6, size_y, size_x);
+  get_mem4Dshort (&(motion->mv),         2, size_y, size_x, 2);
+  get_mem3D      ((byte****)(&(motion->ref_idx)),    2, size_y , size_x);
+
+  motion->mb_field = calloc (size_y * size_x, sizeof(int));
+  if (motion->mb_field == NULL)
+    no_mem_exit("alloc_storable_picture: motion->mb_field");
+
+  get_mem2D (&(motion->field_frame), size_y, size_x);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -350,6 +361,8 @@ StorablePicture* alloc_storable_picture(PictureStructure structure, int size_x,
 {
   StorablePicture *s;
   int   nplane;
+  int   dec;
+  int   ndec = params->NoOfDecoders;
 
   //printf ("Allocating (%s) picture (x=%d, y=%d, x_cr=%d, y_cr=%d)\n", (type == FRAME)?"FRAME":(type == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", size_x, size_y, size_x_cr, size_y_cr);
 
@@ -365,6 +378,51 @@ StorablePicture* alloc_storable_picture(PictureStructure structure, int size_x,
   s->p_img_sub[1] = NULL;
   s->p_img_sub[2] = NULL;
 
+  s->dec_imgY     = NULL;
+  s->dec_imgUV    = NULL;
+  s->mb_error_map = NULL;
+  s->p_dec_img[0] = NULL;
+  s->p_dec_img[1] = NULL;
+  s->p_dec_img[2] = NULL;
+
+  if ((params->rdopt == 3) && (ndec > 0))  //PPAHA_TODO: Need to verify whether both checks are necessary.
+  {
+    get_mem3D(&(s->mb_error_map), ndec, size_y/MB_BLOCK_SIZE, size_x/MB_BLOCK_SIZE);
+    get_mem3Dpel(&(s->dec_imgY), ndec, size_y, size_x);
+
+    // This seems somewhat inefficient. Why not allocate array as [ndec][x] where x goes from 0 to 2?
+    if ((s->p_dec_img[0] = (imgpel***)calloc(ndec,sizeof(imgpel**))) == NULL)
+    {
+      no_mem_exit("mbuffer.c: p_dec_img[0]");
+    }
+    if (img->yuv_format != YUV400)
+    {
+      get_mem4Dpel(&(s->dec_imgUV), ndec, 2, size_y_cr, size_x_cr);
+      if ((s->p_dec_img[1] = (imgpel***)calloc(ndec,sizeof(imgpel**))) == NULL)
+      {
+        no_mem_exit("mbuffer.c: p_dec_img[1]");
+      }
+      if ((s->p_dec_img[2] = (imgpel***)calloc(ndec,sizeof(imgpel**))) == NULL)
+      {
+        no_mem_exit("mbuffer.c: p_dec_img[2]");
+      }
+    }
+  
+    for (dec = 0; dec < ndec; dec++)
+    {
+      s->p_dec_img[0][dec] = s->dec_imgY[dec];
+    }
+
+    if (img->yuv_format != YUV400)
+    {
+      for (dec = 0; dec < ndec; dec++)
+      {
+        s->p_dec_img[1][dec] = s->dec_imgUV[dec][0];
+        s->p_dec_img[2][dec] = s->dec_imgUV[dec][1];
+      }
+    }
+  }
+
   get_mem2Dpel (&(s->imgY), size_y, size_x);
   s->p_img[0] = s->imgY;
   s->p_curr_img = s->p_img[0];
@@ -377,29 +435,21 @@ StorablePicture* alloc_storable_picture(PictureStructure structure, int size_x,
     
   s->p_curr_img_sub = s->p_img_sub[0];
 
-  s->mb_field = calloc (img->PicSizeInMbs, sizeof(int));
-  if (NULL==s->mb_field)
-    no_mem_exit("alloc_storable_picture: s->mb_field");
+  if (params->MbInterlace)
+    get_mem3Dmp    (&s->mv_info, size_y, size_x, 6);
+  else
+    get_mem3Dmp    (&s->mv_info, size_y, size_x, 2);
 
-  get_mem3D      ((byte****)(&(s->ref_idx)),    2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_pic_id), 6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_id),     6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem4Dshort (&(s->mv),         2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
+  alloc_pic_motion(&s->motion, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
 
   if( IS_INDEPENDENT(params) )
   {
     for( nplane=0; nplane<MAX_PLANE; nplane++ )
     {
-      get_mem3D      ((byte****)(&(s->ref_idx_JV[nplane])),    2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem3Dint64 (&(s->ref_pic_id_JV[nplane]), 6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem3Dint64 (&(s->ref_id_JV[nplane]),     6, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-      get_mem4Dshort (&(s->mv_JV[nplane]),         2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
+      alloc_pic_motion(&s->JVmotion[nplane], size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
     }
   }
 
-  get_mem2D (&(s->moving_block),       size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem2D (&(s->field_frame),        size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-
   s->pic_num=0;
   s->frame_num=0;
   s->long_term_frame_idx=0;
@@ -465,6 +515,46 @@ void free_frame_store(FrameStore* f)
   }
 }
 
+void free_pic_motion(PicMotionParams *motion)
+{
+
+  if (motion->ref_pic_id)
+  {
+    free_mem3Dint64 (motion->ref_pic_id);
+    motion->ref_pic_id = NULL;
+  }
+  if (motion->ref_id)
+  {
+    free_mem3Dint64 (motion->ref_id);
+    motion->ref_id = NULL;
+  }
+
+  if (motion->mv)
+  {
+    free_mem4Dshort (motion->mv);
+    motion->mv = NULL;
+  }
+
+  if (motion->ref_idx)
+  {
+    free_mem3D ((byte***)motion->ref_idx);
+    motion->ref_idx = NULL;
+  }
+
+  if (motion->mb_field)
+  {
+    free(motion->mb_field);
+    motion->mb_field=NULL;
+  }
+
+  if (motion->field_frame)
+  {
+    free_mem2D (motion->field_frame);
+    motion->field_frame=NULL;
+  }
+}
+
+
 /*!
  ************************************************************************
  * \brief
@@ -480,68 +570,17 @@ void free_storable_picture(StorablePicture* p)
   int nplane;
   if (p)
   {
-    if (p->ref_idx)
-    {
-      free_mem3D ((byte***)p->ref_idx);
-      p->ref_idx = NULL;
-    }
-
-    if (p->ref_pic_id)
-    {
-      free_mem3Dint64 (p->ref_pic_id);
-      p->ref_pic_id = NULL;
-    }
-    if (p->ref_id)
-    {
-      free_mem3Dint64 (p->ref_id);
-      p->ref_id = NULL;
-    }
-    if (p->mv)
-    {
-      free_mem4Dshort (p->mv);
-      p->mv = NULL;
-    }
+    free_mem3Dmp (p->mv_info);
+    free_pic_motion(&p->motion);
 
     if( IS_INDEPENDENT(params) )
     {
       for( nplane=0; nplane<MAX_PLANE; nplane++ )
       {
-        if (p->ref_idx_JV[nplane])
-        {
-          free_mem3D ((byte***)p->ref_idx_JV[nplane]);
-          p->ref_idx_JV[nplane] = NULL;
-        }
-    
-        if (p->ref_pic_id_JV[nplane])
-        {
-          free_mem3Dint64 (p->ref_pic_id_JV[nplane]);
-          p->ref_pic_id_JV[nplane] = NULL;
-        }
-        if (p->ref_id_JV[nplane])
-        {
-          free_mem3Dint64 (p->ref_id_JV[nplane]);
-          p->ref_id_JV[nplane] = NULL;
-        }
-        if (p->mv_JV[nplane])
-        {
-          free_mem4Dshort (p->mv_JV[nplane]);
-          p->mv_JV[nplane] = NULL;
-        }
+        free_pic_motion(&p->JVmotion[nplane]);
       }
     }
 
-    if (p->moving_block)
-    {
-      free_mem2D (p->moving_block);
-      p->moving_block=NULL;
-    }
-
-    if (p->field_frame)
-    {
-      free_mem2D (p->field_frame);
-      p->field_frame=NULL;
-    }
-
     if (p->imgY)
     {      
       free_mem2Dpel (p->imgY);
@@ -560,6 +599,7 @@ void free_storable_picture(StorablePicture* p)
         free_mem5Dpel (p->imgUV_sub);
         p->imgUV_sub = NULL;
       }
+
       p->p_curr_img     = NULL;
       p->p_curr_img_sub = NULL;
       p->p_img[0]       = NULL;
@@ -576,23 +616,11 @@ void free_storable_picture(StorablePicture* p)
         free_mem4Dpel (p->imgY_sub);
         p->imgY_sub=NULL;
       }
+
       if ( p->imgUV_sub && img->yuv_format != YUV400 && params->ChromaMCBuffer )
       {
-        if ( img->yuv_format == YUV420 )
-        {
-          free_mem5Dpel (p->imgUV_sub);
-          p->imgUV_sub = NULL;
-        }
-        else if ( img->yuv_format == YUV422 )
-        {
-          free_mem5Dpel (p->imgUV_sub);
-          p->imgUV_sub = NULL;
-        }
-        else
-        { // YUV444
-          free_mem5Dpel (p->imgUV_sub);
-          p->imgUV_sub = NULL;
-        }
+        free_mem5Dpel (p->imgUV_sub);
+        p->imgUV_sub = NULL;
       }
     }
 
@@ -602,11 +630,30 @@ void free_storable_picture(StorablePicture* p)
       p->imgUV=NULL;
     }
 
-    if (p->mb_field)
+    if (p->dec_imgY)
     {
-      free(p->mb_field);
-      p->mb_field=NULL;
+      free_mem3Dpel(p->dec_imgY);
     }
+    if (p->dec_imgUV)
+    {
+      free_mem4Dpel(p->dec_imgUV);
+    }
+    for (nplane = 0; nplane < 3; nplane++)
+    {
+      if (p->p_dec_img[nplane])
+      {  
+        free(p->p_dec_img[nplane]);
+        p->p_dec_img[nplane] = NULL;
+      }
+    }
+    if (p->mb_error_map)
+    {
+      free_mem3D(p->mb_error_map);
+    }
+
+    p->mb_error_map = NULL;
+    p->dec_imgY   = NULL;
+    p->dec_imgUV  = NULL;
 
     free(p);
     p = NULL;
@@ -657,16 +704,13 @@ static void unmark_for_reference(FrameStore* fs)
       fs->frame->imgY_sub=NULL;
     }
 
-    if (fs->frame->ref_pic_id)
+    if (fs->frame->imgUV_sub)
     {
-      free_mem3Dint64 (fs->frame->ref_pic_id);
-      fs->frame->ref_pic_id = NULL;
-    }
-    if (fs->frame->ref_id)
-    {
-      free_mem3Dint64 (fs->frame->ref_id);
-      fs->frame->ref_id = NULL;
+      free_mem5Dpel (fs->frame->imgUV_sub);
+      fs->frame->imgUV_sub = NULL;
     }
+
+    free_pic_motion(&fs->frame->motion);
   }
 
   if (fs->top_field)
@@ -677,17 +721,13 @@ static void unmark_for_reference(FrameStore* fs)
       fs->top_field->imgY_sub=NULL;
     }
 
-    if (fs->top_field->ref_pic_id)
+    if (fs->top_field->imgUV_sub)
     {
-      free_mem3Dint64 (fs->top_field->ref_pic_id);
-      fs->top_field->ref_pic_id = NULL;
-    }
-    if (fs->top_field->ref_id)
-    {
-      free_mem3Dint64 (fs->top_field->ref_id);
-      fs->top_field->ref_id = NULL;
+      free_mem5Dpel (fs->top_field->imgUV_sub);
+      fs->top_field->imgUV_sub = NULL;
     }
 
+    free_pic_motion(&fs->top_field->motion);
   }
   if (fs->bottom_field)
   {
@@ -696,18 +736,14 @@ static void unmark_for_reference(FrameStore* fs)
       free_mem4Dpel (fs->bottom_field->imgY_sub);
       fs->bottom_field->imgY_sub=NULL;
     }
-    if (fs->bottom_field->ref_pic_id)
+    if (fs->bottom_field->imgUV_sub)
     {
-      free_mem3Dint64 (fs->bottom_field->ref_pic_id);
-      fs->bottom_field->ref_pic_id = NULL;
+      free_mem5Dpel (fs->bottom_field->imgUV_sub);
+      fs->bottom_field->imgUV_sub = NULL;
     }
-    if (fs->bottom_field->ref_id)
-    {
-      free_mem3Dint64 (fs->bottom_field->ref_id);
-      fs->bottom_field->ref_id = NULL;
-    }
-  }
 
+    free_pic_motion(&fs->bottom_field->motion);
+  }
 }
 
 
@@ -2949,12 +2985,12 @@ void gen_field_ref_ids(StorablePicture *p)
   {
     for (j=0 ; j<p->size_y/4 ; j++)
     {
-        dummylist0= p->ref_idx[LIST_0][j][i];
-        dummylist1= p->ref_idx[LIST_1][j][i];
+        dummylist0= p->motion.ref_idx[LIST_0][j][i];
+        dummylist1= p->motion.ref_idx[LIST_1][j][i];
         //! association with id already known for fields.
-        p->ref_id[LIST_0][j][i] = (dummylist0>=0)? p->ref_pic_num[LIST_0][dummylist0] : 0;
-        p->ref_id[LIST_1][j][i] = (dummylist1>=0)? p->ref_pic_num[LIST_1][dummylist1] : 0;
-        p->field_frame[j][i]=1;
+        p->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? p->ref_pic_num[LIST_0][dummylist0] : 0;
+        p->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? p->ref_pic_num[LIST_1][dummylist1] : 0;
+        p->motion.field_frame[j][i]=1;
     }
   }
 }
@@ -3071,25 +3107,25 @@ void dpb_split_field(FrameStore *fs)
       idiv=i/4;
       currentmb = twosz16*(jdiv/2)+ (idiv)*2 + (jdiv%2);
 
-      if (fs->frame->MbaffFrameFlag  && fs->frame->mb_field[currentmb])
+      if (fs->frame->MbaffFrameFlag  && fs->frame->motion.mb_field[currentmb])
       {
         int list_offset = currentmb%2? 4: 2;
-        dummylist0 = fs->frame->ref_idx[LIST_0][j][i];
-        dummylist1 = fs->frame->ref_idx[LIST_1][j][i];
+        dummylist0 = fs->frame->motion.ref_idx[LIST_0][j][i];
+        dummylist1 = fs->frame->motion.ref_idx[LIST_1][j][i];
         //! association with id already known for fields.
-        fs->frame->ref_id[LIST_0 + list_offset][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[LIST_0 + list_offset][dummylist0] : 0;
-        fs->frame->ref_id[LIST_1 + list_offset][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[LIST_1 + list_offset][dummylist1] : 0;
+        fs->frame->motion.ref_id[LIST_0 + list_offset][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[LIST_0 + list_offset][dummylist0] : 0;
+        fs->frame->motion.ref_id[LIST_1 + list_offset][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[LIST_1 + list_offset][dummylist1] : 0;
         //! need to make association with frames
-        fs->frame->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->frm_ref_pic_num[LIST_0 + list_offset][dummylist0] : 0;
-        fs->frame->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->frm_ref_pic_num[LIST_1 + list_offset][dummylist1] : 0;
+        fs->frame->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->frm_ref_pic_num[LIST_0 + list_offset][dummylist0] : 0;
+        fs->frame->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->frm_ref_pic_num[LIST_1 + list_offset][dummylist1] : 0;
 
       }
       else
       {
-        dummylist0 = fs->frame->ref_idx[LIST_0][j][i];
-        dummylist1 = fs->frame->ref_idx[LIST_1][j][i];
-        fs->frame->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[LIST_0][dummylist0] : -1;
-        fs->frame->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[LIST_1][dummylist1] : -1;
+        dummylist0 = fs->frame->motion.ref_idx[LIST_0][j][i];
+        dummylist1 = fs->frame->motion.ref_idx[LIST_1][j][i];
+        fs->frame->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->ref_pic_num[LIST_0][dummylist0] : -1;
+        fs->frame->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->ref_pic_num[LIST_1][dummylist1] : -1;
       }
     }
   }
@@ -3107,29 +3143,29 @@ void dpb_split_field(FrameStore *fs)
 
         currentmb = twosz16*(jdiv/2)+ (idiv)*2 + (jdiv%2);
         // Assign field mvs attached to MB-Frame buffer to the proper buffer
-        if (fs->frame->mb_field[currentmb])
+        if (fs->frame->motion.mb_field[currentmb])
         {
-          fs->bottom_field->field_frame[j][i] = fs->top_field->field_frame[j][i]=1;
-          fs->frame->field_frame[2*j][i] = fs->frame->field_frame[2*j+1][i]=1;
-
-          fs->bottom_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj4][i][0];
-          fs->bottom_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj4][i][1];
-          fs->bottom_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj4][i][0];
-          fs->bottom_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj4][i][1];
-          fs->bottom_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj4][i];
-          fs->bottom_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj4][i];
-          fs->bottom_field->ref_id[LIST_0][j][i] = fs->frame->ref_id[LIST_0+4][jj4][i];
-          fs->bottom_field->ref_id[LIST_1][j][i] = fs->frame->ref_id[LIST_1+4][jj4][i];
-
-
-          fs->top_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj][i][0];
-          fs->top_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj][i][1];
-          fs->top_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj][i][0];
-          fs->top_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj][i][1];
-          fs->top_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj][i];
-          fs->top_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj][i];
-          fs->top_field->ref_id[LIST_0][j][i] = fs->frame->ref_id[LIST_0+2][jj][i];
-          fs->top_field->ref_id[LIST_1][j][i] = fs->frame->ref_id[LIST_1+2][jj][i];
+          fs->bottom_field->motion.field_frame[j][i] = fs->top_field->motion.field_frame[j][i]=1;
+          fs->frame->motion.field_frame[2*j][i] = fs->frame->motion.field_frame[2*j+1][i]=1;
+
+          fs->bottom_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj4][i][0];
+          fs->bottom_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj4][i][1];
+          fs->bottom_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj4][i][0];
+          fs->bottom_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj4][i][1];
+          fs->bottom_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj4][i];
+          fs->bottom_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj4][i];
+          fs->bottom_field->motion.ref_id[LIST_0][j][i] = fs->frame->motion.ref_id[LIST_0+4][jj4][i];
+          fs->bottom_field->motion.ref_id[LIST_1][j][i] = fs->frame->motion.ref_id[LIST_1+4][jj4][i];
+
+
+          fs->top_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj][i][0];
+          fs->top_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj][i][1];
+          fs->top_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj][i][0];
+          fs->top_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj][i][1];
+          fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj][i];
+          fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj][i];
+          fs->top_field->motion.ref_id[LIST_0][j][i] = fs->frame->motion.ref_id[LIST_0+2][jj][i];
+          fs->top_field->motion.ref_id[LIST_1][j][i] = fs->frame->motion.ref_id[LIST_1+2][jj][i];
         }
       }
     }
@@ -3149,47 +3185,47 @@ void dpb_split_field(FrameStore *fs)
 
         currentmb = twosz16*(jdiv/2)+ (idiv)*2 + (jdiv%2);
 
-        if (!fs->frame->MbaffFrameFlag  || !fs->frame->mb_field[currentmb])
+        if (!fs->frame->MbaffFrameFlag  || !fs->frame->motion.mb_field[currentmb])
         {
-          fs->frame->field_frame[2*j+1][i] = fs->frame->field_frame[2*j][i]=0;
+          fs->frame->motion.field_frame[2*j+1][i] = fs->frame->motion.field_frame[2*j][i]=0;
 
-          fs->top_field->field_frame[j][i] = fs->bottom_field->field_frame[j][i] = 0;
+          fs->top_field->motion.field_frame[j][i] = fs->bottom_field->motion.field_frame[j][i] = 0;
 
-          fs->top_field->mv[LIST_0][j][i][0] = fs->bottom_field->mv[LIST_0][j][i][0] = fs->frame->mv[LIST_0][jj][ii][0];
-          fs->top_field->mv[LIST_0][j][i][1] = fs->bottom_field->mv[LIST_0][j][i][1] = fs->frame->mv[LIST_0][jj][ii][1];
-          fs->top_field->mv[LIST_1][j][i][0] = fs->bottom_field->mv[LIST_1][j][i][0] = fs->frame->mv[LIST_1][jj][ii][0];
-          fs->top_field->mv[LIST_1][j][i][1] = fs->bottom_field->mv[LIST_1][j][i][1] = fs->frame->mv[LIST_1][jj][ii][1];
+          fs->top_field->motion.mv[LIST_0][j][i][0] = fs->bottom_field->motion.mv[LIST_0][j][i][0] = fs->frame->motion.mv[LIST_0][jj][ii][0];
+          fs->top_field->motion.mv[LIST_0][j][i][1] = fs->bottom_field->motion.mv[LIST_0][j][i][1] = fs->frame->motion.mv[LIST_0][jj][ii][1];
+          fs->top_field->motion.mv[LIST_1][j][i][0] = fs->bottom_field->motion.mv[LIST_1][j][i][0] = fs->frame->motion.mv[LIST_1][jj][ii][0];
+          fs->top_field->motion.mv[LIST_1][j][i][1] = fs->bottom_field->motion.mv[LIST_1][j][i][1] = fs->frame->motion.mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
-          if (fs->frame->ref_idx[LIST_0][jj][ii] == -1)
-            fs->top_field->ref_idx[LIST_0][j][i] = fs->bottom_field->ref_idx[LIST_0][j][i] = - 1;
+          if (fs->frame->motion.ref_idx[LIST_0][jj][ii] == -1)
+            fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->bottom_field->motion.ref_idx[LIST_0][j][i] = - 1;
           else
           {
-            dummylist0=fs->top_field->ref_idx[LIST_0][j][i] = fs->bottom_field->ref_idx[LIST_0][j][i] = fs->frame->ref_idx[LIST_0][jj][ii];
-            fs->top_field   ->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->top_ref_pic_num[LIST_0][dummylist0] : 0;
-            fs->bottom_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->bottom_ref_pic_num[LIST_0][dummylist0] : 0;
+            dummylist0=fs->top_field->motion.ref_idx[LIST_0][j][i] = fs->bottom_field->motion.ref_idx[LIST_0][j][i] = fs->frame->motion.ref_idx[LIST_0][jj][ii];
+            fs->top_field   ->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->top_ref_pic_num[LIST_0][dummylist0] : 0;
+            fs->bottom_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->frame->bottom_ref_pic_num[LIST_0][dummylist0] : 0;
           }
 
-          if (fs->frame->ref_idx[LIST_1][jj][ii] == -1)
-            fs->top_field->ref_idx[LIST_1][j][i] = fs->bottom_field->ref_idx[LIST_1][j][i] = - 1;
+          if (fs->frame->motion.ref_idx[LIST_1][jj][ii] == -1)
+            fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->bottom_field->motion.ref_idx[LIST_1][j][i] = - 1;
           else
           {
-            dummylist1=fs->top_field->ref_idx[LIST_1][j][i] = fs->bottom_field->ref_idx[LIST_1][j][i] = fs->frame->ref_idx[LIST_1][jj][ii];
+            dummylist1=fs->top_field->motion.ref_idx[LIST_1][j][i] = fs->bottom_field->motion.ref_idx[LIST_1][j][i] = fs->frame->motion.ref_idx[LIST_1][jj][ii];
 
-            fs->top_field   ->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->top_ref_pic_num[LIST_1][dummylist1] : 0;
-            fs->bottom_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->bottom_ref_pic_num[LIST_1][dummylist1] : 0;
+            fs->top_field   ->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->top_ref_pic_num[LIST_1][dummylist1] : 0;
+            fs->bottom_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->frame->bottom_ref_pic_num[LIST_1][dummylist1] : 0;
           }
         }
         else
         {
-          fs->frame->field_frame[2*j+1][i] = fs->frame->field_frame[2*j][i]= fs->frame->mb_field[currentmb];
+          fs->frame->motion.field_frame[2*j+1][i] = fs->frame->motion.field_frame[2*j][i]= fs->frame->motion.mb_field[currentmb];
         }
       }
     }
   }
   else
   {
-    memset( &(fs->frame->field_frame[0][0]), 0, fs->frame->size_y * (fs->frame->size_x >>4) * sizeof(byte));
+    memset( &(fs->frame->motion.field_frame[0][0]), 0, fs->frame->size_y * (fs->frame->size_x >>4) * sizeof(byte));
   }
 }
 
@@ -3297,41 +3333,41 @@ void dpb_combine_field(FrameStore *fs)
     jj4 = jj + 4;
     for (i=0 ; i<fs->top_field->size_x/4 ; i++)
     {
-      fs->frame->field_frame[jj][i]= fs->frame->field_frame[jj4][i]=1;
+      fs->frame->motion.field_frame[jj][i]= fs->frame->motion.field_frame[jj4][i]=1;
 
-      fs->frame->mv[LIST_0][jj][i][0] = fs->top_field->mv[LIST_0][j][i][0];
-      fs->frame->mv[LIST_0][jj][i][1] = fs->top_field->mv[LIST_0][j][i][1] ;
-      fs->frame->mv[LIST_1][jj][i][0] = fs->top_field->mv[LIST_1][j][i][0];
-      fs->frame->mv[LIST_1][jj][i][1] = fs->top_field->mv[LIST_1][j][i][1] ;
+      fs->frame->motion.mv[LIST_0][jj][i][0] = fs->top_field->motion.mv[LIST_0][j][i][0];
+      fs->frame->motion.mv[LIST_0][jj][i][1] = fs->top_field->motion.mv[LIST_0][j][i][1] ;
+      fs->frame->motion.mv[LIST_1][jj][i][0] = fs->top_field->motion.mv[LIST_1][j][i][0];
+      fs->frame->motion.mv[LIST_1][jj][i][1] = fs->top_field->motion.mv[LIST_1][j][i][1] ;
 
-      dummylist0=fs->frame->ref_idx[LIST_0][jj][i]  = fs->top_field->ref_idx[LIST_0][j][i];
-      dummylist1=fs->frame->ref_idx[LIST_1][jj][i]  = fs->top_field->ref_idx[LIST_1][j][i];
+      dummylist0=fs->frame->motion.ref_idx[LIST_0][jj][i]  = fs->top_field->motion.ref_idx[LIST_0][j][i];
+      dummylist1=fs->frame->motion.ref_idx[LIST_1][jj][i]  = fs->top_field->motion.ref_idx[LIST_1][j][i];
 
       //! association with id already known for fields.
-      fs->top_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->top_field->ref_pic_num[LIST_0][dummylist0] : 0;
-      fs->top_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->top_field->ref_pic_num[LIST_1][dummylist1] : 0;
+      fs->top_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->top_field->ref_pic_num[LIST_0][dummylist0] : 0;
+      fs->top_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->top_field->ref_pic_num[LIST_1][dummylist1] : 0;
 
       //! need to make association with frames
-      fs->frame->ref_id[LIST_0][jj][i] = (dummylist0>=0)? fs->top_field->frm_ref_pic_num[LIST_0][dummylist0] : 0;
-      fs->frame->ref_id[LIST_1][jj][i] = (dummylist1>=0)? fs->top_field->frm_ref_pic_num[LIST_1][dummylist1] : 0;
+      fs->frame->motion.ref_id[LIST_0][jj][i] = (dummylist0>=0)? fs->top_field->frm_ref_pic_num[LIST_0][dummylist0] : 0;
+      fs->frame->motion.ref_id[LIST_1][jj][i] = (dummylist1>=0)? fs->top_field->frm_ref_pic_num[LIST_1][dummylist1] : 0;
 
-      fs->frame->mv[LIST_0][jj4][i][0] = fs->bottom_field->mv[LIST_0][j][i][0];
-      fs->frame->mv[LIST_0][jj4][i][1] = fs->bottom_field->mv[LIST_0][j][i][1] ;
-      fs->frame->mv[LIST_1][jj4][i][0] = fs->bottom_field->mv[LIST_1][j][i][0];
-      fs->frame->mv[LIST_1][jj4][i][1] = fs->bottom_field->mv[LIST_1][j][i][1] ;
+      fs->frame->motion.mv[LIST_0][jj4][i][0] = fs->bottom_field->motion.mv[LIST_0][j][i][0];
+      fs->frame->motion.mv[LIST_0][jj4][i][1] = fs->bottom_field->motion.mv[LIST_0][j][i][1] ;
+      fs->frame->motion.mv[LIST_1][jj4][i][0] = fs->bottom_field->motion.mv[LIST_1][j][i][0];
+      fs->frame->motion.mv[LIST_1][jj4][i][1] = fs->bottom_field->motion.mv[LIST_1][j][i][1] ;
 
-      dummylist0=fs->frame->ref_idx[LIST_0][jj4][i]  = fs->bottom_field->ref_idx[LIST_0][j][i];
-      dummylist1=fs->frame->ref_idx[LIST_1][jj4][i]  = fs->bottom_field->ref_idx[LIST_1][j][i];
+      dummylist0=fs->frame->motion.ref_idx[LIST_0][jj4][i]  = fs->bottom_field->motion.ref_idx[LIST_0][j][i];
+      dummylist1=fs->frame->motion.ref_idx[LIST_1][jj4][i]  = fs->bottom_field->motion.ref_idx[LIST_1][j][i];
 
-      fs->bottom_field->ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->bottom_field->ref_pic_num[LIST_0][dummylist0] : 0;
-      fs->bottom_field->ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->bottom_field->ref_pic_num[LIST_1][dummylist1] : 0;
+      fs->bottom_field->motion.ref_id[LIST_0][j][i] = (dummylist0>=0)? fs->bottom_field->ref_pic_num[LIST_0][dummylist0] : 0;
+      fs->bottom_field->motion.ref_id[LIST_1][j][i] = (dummylist1>=0)? fs->bottom_field->ref_pic_num[LIST_1][dummylist1] : 0;
 
       //! need to make association with frames
-      fs->frame->ref_id[LIST_0][jj4][i] = (dummylist0>=0)? fs->bottom_field->frm_ref_pic_num[LIST_0][dummylist0] : -1;
-      fs->frame->ref_id[LIST_1][jj4][i] = (dummylist1>=0)? fs->bottom_field->frm_ref_pic_num[LIST_1][dummylist1] : -1;
+      fs->frame->motion.ref_id[LIST_0][jj4][i] = (dummylist0>=0)? fs->bottom_field->frm_ref_pic_num[LIST_0][dummylist0] : -1;
+      fs->frame->motion.ref_id[LIST_1][jj4][i] = (dummylist1>=0)? fs->bottom_field->frm_ref_pic_num[LIST_1][dummylist1] : -1;
 
-      fs->top_field->field_frame[j][i]=1;
-      fs->bottom_field->field_frame[j][i]=1;
+      fs->top_field->motion.field_frame[j][i]=1;
+      fs->bottom_field->motion.field_frame[j][i]=1;
     }
   }
 }
@@ -3454,6 +3490,21 @@ void fill_frame_num_gap(ImageParameters *img)
   img->nal_reference_idc = nal_ref_idc_bak;
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate motion parameter memory for colocated structure
+ *
+ ************************************************************************
+ */
+void alloc_motion_params(MotionParams *ftype, int size_y, int size_x)
+{
+  get_mem3Dint64 (&(ftype->ref_pic_id), 2, size_y, size_x);
+  get_mem4Dshort (&(ftype->mv)        , 2, size_y, size_x, 2);
+  get_mem3D      ((byte****)(&(ftype->ref_idx)) , 2, size_y, size_x);
+  get_mem2D      (&(ftype->moving_block) , size_y, size_x);
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -3481,25 +3532,12 @@ ColocatedParams* alloc_colocated(int size_x, int size_y, int mb_adaptive_frame_f
   s->size_x = size_x;
   s->size_y = size_y;
 
-
-  get_mem3D      ((byte****)(&(s->ref_idx))   , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem3Dint64 (&(s->ref_pic_id), 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem4Dshort (&(s->mv)        , 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE,2 );
-
-  get_mem2D      (&(s->moving_block),  size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
-  get_mem2D      (&(s->field_frame) , size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
+  alloc_motion_params(&s->frame, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
 
   if (mb_adaptive_frame_field_flag)
   {
-    get_mem3D      ((byte****)(&(s->top_ref_idx))   , 2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
-    get_mem3Dint64 (&(s->top_ref_pic_id),             2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
-    get_mem4Dshort (&(s->top_mv),                     2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE, 2);
-    get_mem2D (&(s->top_moving_block),                   size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
-
-    get_mem3D      ((byte****)(&(s->bottom_ref_idx)), 2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
-    get_mem3Dint64 (&(s->bottom_ref_pic_id),          2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
-    get_mem4Dshort (&(s->bottom_mv),                  2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE, 2);
-    get_mem2D (&(s->bottom_moving_block),                size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE);
+    alloc_motion_params(&s->top   , size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
+    alloc_motion_params(&s->bottom, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
   }
 
   s->mb_adaptive_frame_field_flag  = mb_adaptive_frame_field_flag;
@@ -3507,6 +3545,27 @@ ColocatedParams* alloc_colocated(int size_x, int size_y, int mb_adaptive_frame_f
   return s;
 }
 
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Free motion parameter memory for colocated structure
+ *
+ ************************************************************************
+ */
+void free_motion_params(MotionParams *ftype)
+{
+  free_mem3Dint64 (ftype->ref_pic_id);
+  free_mem3D      ((byte***)ftype->ref_idx);
+  free_mem4Dshort (ftype->mv);
+
+  if (ftype->moving_block)
+  {
+    free_mem2D (ftype->moving_block);
+    ftype->moving_block=NULL;
+  }
+}
+
 /*!
  ************************************************************************
  * \brief
@@ -3521,45 +3580,12 @@ void free_colocated(ColocatedParams* p)
 {
   if (p)
   {
-    free_mem3D      ((byte***)p->ref_idx);
-    free_mem3Dint64 (p->ref_pic_id);
-    free_mem4Dshort (p->mv);
-
-    if (p->moving_block)
-    {
-      free_mem2D (p->moving_block);
-      p->moving_block=NULL;
-    }
-    if (p->field_frame)
-    {
-      free_mem2D (p->field_frame);
-      p->field_frame=NULL;
-    }
+    free_motion_params(&p->frame);
 
     if (p->mb_adaptive_frame_field_flag)
     {
-      free_mem3D      ((byte***)p->top_ref_idx);
-      free_mem3Dint64 (p->top_ref_pic_id);
-      free_mem4Dshort (p->top_mv);
-
-
-      if (p->top_moving_block)
-      {
-        free_mem2D (p->top_moving_block);
-        p->top_moving_block=NULL;
-      }
-
-      free_mem3D      ((byte***)p->bottom_ref_idx);
-      free_mem3Dint64 (p->bottom_ref_pic_id);
-      free_mem4Dshort (p->bottom_mv);
-
-
-      if (p->bottom_moving_block)
-      {
-        free_mem2D (p->bottom_moving_block);
-        p->bottom_moving_block=NULL;
-      }
-
+      free_motion_params(&p->top   );
+      free_motion_params(&p->bottom);
     }
 
     free(p);
@@ -3579,6 +3605,7 @@ void free_colocated(ColocatedParams* p)
 void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 {
   StorablePicture *fs, *fs_top, *fs_bottom;
+  MotionParams *ftype = NULL;
   int i,j, ii, jj, jdiv;
 
   fs_top = fs_bottom = fs = listX[LIST_1 ][0];
@@ -3607,7 +3634,8 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
   }
 
   if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
-  {
+  {    
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       jdiv = j>>1;
@@ -3615,7 +3643,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
 
-        if (img->MbaffFrameFlag && fs->field_frame[j][i])
+        if (img->MbaffFrameFlag && fs->motion.field_frame[j][i])
         {
           //! Assign frame buffers for field MBs
           //! Check whether we should use top or bottom field mvs.
@@ -3623,41 +3651,41 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 
           if (iabs(enc_picture->poc - fs_bottom->poc) > iabs(enc_picture->poc - fs_top->poc) )
           {
-            p->mv[LIST_0][j][i][0]    = fs_top->mv[LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]    = fs_top->mv[LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]    = fs_top->mv[LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]    = fs_top->mv[LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]  = fs_top->ref_idx[LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]  = fs_top->ref_idx[LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i]   = fs->ref_id[LIST_0][jj][i];
-            p->ref_pic_id[LIST_1][j][i]   = fs->ref_id[LIST_1][jj][i];
+            ftype->mv[LIST_0][j][i][0]    = fs_top->motion.mv[LIST_0][jdiv][i][0];
+            ftype->mv[LIST_0][j][i][1]    = fs_top->motion.mv[LIST_0][jdiv][i][1] ;
+            ftype->mv[LIST_1][j][i][0]    = fs_top->motion.mv[LIST_1][jdiv][i][0];
+            ftype->mv[LIST_1][j][i][1]    = fs_top->motion.mv[LIST_1][jdiv][i][1] ;
+            ftype->ref_idx[LIST_0][j][i]  = fs_top->motion.ref_idx[LIST_0][jdiv][i];
+            ftype->ref_idx[LIST_1][j][i]  = fs_top->motion.ref_idx[LIST_1][jdiv][i];
+            ftype->ref_pic_id[LIST_0][j][i]   = fs->motion.ref_id[LIST_0][jj][i];
+            ftype->ref_pic_id[LIST_1][j][i]   = fs->motion.ref_id[LIST_1][jj][i];
 
             p->is_long_term             = fs_top->is_long_term;
           }
           else
           {
-            p->mv[LIST_0][j][i][0]      = fs_bottom->mv[LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]      = fs_bottom->mv[LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]      = fs_bottom->mv[LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]      = fs_bottom->mv[LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]    = fs_bottom->ref_idx[LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]    = fs_bottom->ref_idx[LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj + 4][i];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj + 4][i];
+            ftype->mv[LIST_0][j][i][0]      = fs_bottom->motion.mv[LIST_0][jdiv][i][0];
+            ftype->mv[LIST_0][j][i][1]      = fs_bottom->motion.mv[LIST_0][jdiv][i][1] ;
+            ftype->mv[LIST_1][j][i][0]      = fs_bottom->motion.mv[LIST_1][jdiv][i][0];
+            ftype->mv[LIST_1][j][i][1]      = fs_bottom->motion.mv[LIST_1][jdiv][i][1] ;
+            ftype->ref_idx[LIST_0][j][i]    = fs_bottom->motion.ref_idx[LIST_0][jdiv][i];
+            ftype->ref_idx[LIST_1][j][i]    = fs_bottom->motion.ref_idx[LIST_1][jdiv][i];
+            ftype->ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj + 4][i];
+            ftype->ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj + 4][i];
 
             p->is_long_term             = fs_bottom->is_long_term;
           }
         }
         else
         {
-          p->mv[LIST_0][j][i][0]      = fs->mv[LIST_0][j][i][0];
-          p->mv[LIST_0][j][i][1]      = fs->mv[LIST_0][j][i][1] ;
-          p->mv[LIST_1][j][i][0]      = fs->mv[LIST_1][j][i][0];
-          p->mv[LIST_1][j][i][1]      = fs->mv[LIST_1][j][i][1] ;
-          p->ref_idx[LIST_0][j][i]    = fs->ref_idx[LIST_0][j][i];
-          p->ref_idx[LIST_1][j][i]    = fs->ref_idx[LIST_1][j][i];
-          p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][j][i];
-          p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][j][i];
+          ftype->mv[LIST_0][j][i][0]      = fs->motion.mv[LIST_0][j][i][0];
+          ftype->mv[LIST_0][j][i][1]      = fs->motion.mv[LIST_0][j][i][1] ;
+          ftype->mv[LIST_1][j][i][0]      = fs->motion.mv[LIST_1][j][i][0];
+          ftype->mv[LIST_1][j][i][1]      = fs->motion.mv[LIST_1][j][i][1] ;
+          ftype->ref_idx[LIST_0][j][i]    = fs->motion.ref_idx[LIST_0][j][i];
+          ftype->ref_idx[LIST_1][j][i]    = fs->motion.ref_idx[LIST_1][j][i];
+          ftype->ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][j][i];
+          ftype->ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][j][i];
 
           p->is_long_term             = fs->is_long_term;
         }
@@ -3669,6 +3697,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
   //! Generate field MVs from Frame MVs
   if (img->structure || img->MbaffFrameFlag)
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/8 ; j++)
     {
       jj = RSD(j);
@@ -3678,102 +3707,102 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         //! Do nothing if macroblock as field coded in MB-AFF
         if (!img->MbaffFrameFlag )
         {
-          p->mv[LIST_0][j][i][0] = fs->mv[LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1] = fs->mv[LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0] = fs->mv[LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1] = fs->mv[LIST_1][jj][ii][1];
+          ftype->mv[LIST_0][j][i][0] = fs->motion.mv[LIST_0][jj][ii][0];
+          ftype->mv[LIST_0][j][i][1] = fs->motion.mv[LIST_0][jj][ii][1];
+          ftype->mv[LIST_1][j][i][0] = fs->motion.mv[LIST_1][jj][ii][0];
+          ftype->mv[LIST_1][j][i][1] = fs->motion.mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
 
-          if (fs->ref_idx[LIST_0][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_0][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_0][j][i] = -1;
-            p->ref_pic_id[LIST_0][j][i] = -1;
+            ftype->ref_idx   [LIST_0][j][i] = -1;
+            ftype->ref_pic_id[LIST_0][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_0][j][i] = fs->ref_idx[LIST_0][jj][ii] ;
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id [LIST_0][jj][ii];
+            ftype->ref_idx   [LIST_0][j][i] = fs->motion.ref_idx[LIST_0][jj][ii] ;
+            ftype->ref_pic_id[LIST_0][j][i] = fs->motion.ref_id [LIST_0][jj][ii];
           }
 
-          if (fs->ref_idx[LIST_1][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_1][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_1][j][i] = -1;
-            p->ref_pic_id[LIST_1][j][i] = -1;
+            ftype->ref_idx   [LIST_1][j][i] = -1;
+            ftype->ref_pic_id[LIST_1][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_1][j][i] = fs->ref_idx[LIST_1][jj][ii];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id [LIST_1][jj][ii];
+            ftype->ref_idx   [LIST_1][j][i] = fs->motion.ref_idx[LIST_1][jj][ii];
+            ftype->ref_pic_id[LIST_1][j][i] = fs->motion.ref_id [LIST_1][jj][ii];
           }
 
           p->is_long_term = fs->is_long_term;
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->moving_block[j][i] =
+            ftype->moving_block[j][i] =
               !((!p->is_long_term
-              && ((p->ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->ref_idx[LIST_0][j][i] == -1)
-              &&  (p->ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((ftype->ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((ftype->ref_idx[LIST_0][j][i] == -1)
+              &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
           }
         }
         else
         {
-          p->bottom_mv[LIST_0][j][i][0] = fs_bottom->mv[LIST_0][jj][ii][0];
-          p->bottom_mv[LIST_0][j][i][1] = fs_bottom->mv[LIST_0][jj][ii][1];
-          p->bottom_mv[LIST_1][j][i][0] = fs_bottom->mv[LIST_1][jj][ii][0];
-          p->bottom_mv[LIST_1][j][i][1] = fs_bottom->mv[LIST_1][jj][ii][1];
-          p->bottom_ref_idx[LIST_0][j][i] = fs_bottom->ref_idx[LIST_0][jj][ii];
-          p->bottom_ref_idx[LIST_1][j][i] = fs_bottom->ref_idx[LIST_1][jj][ii];
-          p->bottom_ref_pic_id[LIST_0][j][i] = fs_bottom->ref_id[LIST_0][jj][ii];
-          p->bottom_ref_pic_id[LIST_1][j][i] = fs_bottom->ref_id[LIST_1][jj][ii];
+          p->bottom.mv[LIST_0][j][i][0] = fs_bottom->motion.mv[LIST_0][jj][ii][0];
+          p->bottom.mv[LIST_0][j][i][1] = fs_bottom->motion.mv[LIST_0][jj][ii][1];
+          p->bottom.mv[LIST_1][j][i][0] = fs_bottom->motion.mv[LIST_1][jj][ii][0];
+          p->bottom.mv[LIST_1][j][i][1] = fs_bottom->motion.mv[LIST_1][jj][ii][1];
+          p->bottom.ref_idx[LIST_0][j][i] = fs_bottom->motion.ref_idx[LIST_0][jj][ii];
+          p->bottom.ref_idx[LIST_1][j][i] = fs_bottom->motion.ref_idx[LIST_1][jj][ii];
+          p->bottom.ref_pic_id[LIST_0][j][i] = fs_bottom->motion.ref_id[LIST_0][jj][ii];
+          p->bottom.ref_pic_id[LIST_1][j][i] = fs_bottom->motion.ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->bottom_moving_block[j][i] =
+            p->bottom.moving_block[j][i] =
               !((!fs_bottom->is_long_term
-              && ((p->bottom_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->bottom_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->bottom_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->bottom.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->bottom.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->bottom.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          p->top_mv[LIST_0][j][i][0] = fs_top->mv[LIST_0][jj][ii][0];
-          p->top_mv[LIST_0][j][i][1] = fs_top->mv[LIST_0][jj][ii][1];
-          p->top_mv[LIST_1][j][i][0] = fs_top->mv[LIST_1][jj][ii][0];
-          p->top_mv[LIST_1][j][i][1] = fs_top->mv[LIST_1][jj][ii][1];
-          p->top_ref_idx[LIST_0][j][i] = fs_top->ref_idx[LIST_0][jj][ii];
-          p->top_ref_idx[LIST_1][j][i] = fs_top->ref_idx[LIST_1][jj][ii];
-          p->top_ref_pic_id[LIST_0][j][i] = fs_top->ref_id[LIST_0][jj][ii];
-          p->top_ref_pic_id[LIST_1][j][i] = fs_top->ref_id[LIST_1][jj][ii];
+          p->top.mv[LIST_0][j][i][0] = fs_top->motion.mv[LIST_0][jj][ii][0];
+          p->top.mv[LIST_0][j][i][1] = fs_top->motion.mv[LIST_0][jj][ii][1];
+          p->top.mv[LIST_1][j][i][0] = fs_top->motion.mv[LIST_1][jj][ii][0];
+          p->top.mv[LIST_1][j][i][1] = fs_top->motion.mv[LIST_1][jj][ii][1];
+          p->top.ref_idx[LIST_0][j][i] = fs_top->motion.ref_idx[LIST_0][jj][ii];
+          p->top.ref_idx[LIST_1][j][i] = fs_top->motion.ref_idx[LIST_1][jj][ii];
+          p->top.ref_pic_id[LIST_0][j][i] = fs_top->motion.ref_id[LIST_0][jj][ii];
+          p->top.ref_pic_id[LIST_1][j][i] = fs_top->motion.ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->top_moving_block[j][i] =
+            p->top.moving_block[j][i] =
               !((!fs_top->is_long_term
-              && ((p->top_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->top_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->top_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->top.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->top.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->top.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->field_frame[2*j][i])
+          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->motion.field_frame[2*j][i])
           {
-            p->top_mv[LIST_0][j][i][1] /= 2;
-            p->top_mv[LIST_1][j][i][1] /= 2;
-            p->bottom_mv[LIST_0][j][i][1] /= 2;
-            p->bottom_mv[LIST_1][j][i][1] /= 2;
+            p->top.mv[LIST_0][j][i][1] /= 2;
+            p->top.mv[LIST_1][j][i][1] /= 2;
+            p->bottom.mv[LIST_0][j][i][1] /= 2;
+            p->bottom.mv[LIST_1][j][i][1] /= 2;
           }
 
         }
@@ -3789,6 +3818,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 
     if (!img->structure)
     {
+      ftype = &p->frame;
       for (j=0 ; j < (fs->size_y>>2) ; j++)
       {
         jdiv = j>>1;
@@ -3796,32 +3826,32 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
         for (i=0 ; i < (fs->size_x>>2) ; i++)
         {
 
-          if (fs->field_frame[j][i])
+          if (fs->motion.field_frame[j][i])
           {
             if (iabs(enc_picture->poc - fs->bottom_field->poc) > iabs(enc_picture->poc - fs->top_field->poc))
             {
-              p->mv[LIST_0][j][i][0] = fs->top_field->mv[LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->top_field->mv[LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->top_field->mv[LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->top_field->mv[LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->top_field->ref_idx[LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->top_field->ref_idx[LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i]   = fs->ref_id[LIST_0][jj][i];
-              p->ref_pic_id[LIST_1][j][i]   = fs->ref_id[LIST_1][jj][i];
+              ftype->mv[LIST_0][j][i][0] = fs->top_field->motion.mv[LIST_0][jdiv][i][0];
+              ftype->mv[LIST_0][j][i][1] = fs->top_field->motion.mv[LIST_0][jdiv][i][1] ;
+              ftype->mv[LIST_1][j][i][0] = fs->top_field->motion.mv[LIST_1][jdiv][i][0];
+              ftype->mv[LIST_1][j][i][1] = fs->top_field->motion.mv[LIST_1][jdiv][i][1] ;
+
+              ftype->ref_idx[LIST_0][j][i]  = fs->top_field->motion.ref_idx[LIST_0][jdiv][i];
+              ftype->ref_idx[LIST_1][j][i]  = fs->top_field->motion.ref_idx[LIST_1][jdiv][i];
+              ftype->ref_pic_id[LIST_0][j][i]   = fs->motion.ref_id[LIST_0][jj][i];
+              ftype->ref_pic_id[LIST_1][j][i]   = fs->motion.ref_id[LIST_1][jj][i];
               p->is_long_term               = fs->top_field->is_long_term;
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = fs->bottom_field->mv[LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->bottom_field->mv[LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->bottom_field->mv[LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->bottom_field->mv[LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->bottom_field->ref_idx[LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->bottom_field->ref_idx[LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][jj + 4][i];
-              p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][jj + 4][i];
+              ftype->mv[LIST_0][j][i][0] = fs->bottom_field->motion.mv[LIST_0][jdiv][i][0];
+              ftype->mv[LIST_0][j][i][1] = fs->bottom_field->motion.mv[LIST_0][jdiv][i][1] ;
+              ftype->mv[LIST_1][j][i][0] = fs->bottom_field->motion.mv[LIST_1][jdiv][i][0];
+              ftype->mv[LIST_1][j][i][1] = fs->bottom_field->motion.mv[LIST_1][jdiv][i][1] ;
+
+              ftype->ref_idx[LIST_0][j][i]  = fs->bottom_field->motion.ref_idx[LIST_0][jdiv][i];
+              ftype->ref_idx[LIST_1][j][i]  = fs->bottom_field->motion.ref_idx[LIST_1][jdiv][i];
+              ftype->ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][jj + 4][i];
+              ftype->ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][jj + 4][i];
               p->is_long_term             = fs->bottom_field->is_long_term;
             }
           }
@@ -3835,6 +3865,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 
   if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
   {
+    ftype = &p->frame;
     for (j=0 ; j < (fs->size_y>>2) ; j++)
     {
       jj = RSD(j);
@@ -3842,33 +3873,34 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
 
-        p->mv[LIST_0][j][i][0]=p->mv[LIST_0][jj][ii][0];
-        p->mv[LIST_0][j][i][1]=p->mv[LIST_0][jj][ii][1];
-        p->mv[LIST_1][j][i][0]=p->mv[LIST_1][jj][ii][0];
-        p->mv[LIST_1][j][i][1]=p->mv[LIST_1][jj][ii][1];
+        ftype->mv[LIST_0][j][i][0]=ftype->mv[LIST_0][jj][ii][0];
+        ftype->mv[LIST_0][j][i][1]=ftype->mv[LIST_0][jj][ii][1];
+        ftype->mv[LIST_1][j][i][0]=ftype->mv[LIST_1][jj][ii][0];
+        ftype->mv[LIST_1][j][i][1]=ftype->mv[LIST_1][jj][ii][1];
 
-        p->ref_idx[LIST_0][j][i]=p->ref_idx[LIST_0][jj][ii];
-        p->ref_idx[LIST_1][j][i]=p->ref_idx[LIST_1][jj][ii];
-        p->ref_pic_id[LIST_0][j][i] = p->ref_pic_id[LIST_0][jj][ii];
-        p->ref_pic_id[LIST_1][j][i] = p->ref_pic_id[LIST_1][jj][ii];
+        ftype->ref_idx[LIST_0][j][i]=ftype->ref_idx[LIST_0][jj][ii];
+        ftype->ref_idx[LIST_1][j][i]=ftype->ref_idx[LIST_1][jj][ii];
+        ftype->ref_pic_id[LIST_0][j][i] = ftype->ref_pic_id[LIST_0][jj][ii];
+        ftype->ref_pic_id[LIST_1][j][i] = ftype->ref_pic_id[LIST_1][jj][ii];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]=
+          ftype->moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((ftype->ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((ftype->ref_idx[LIST_0][j][i] == -1)
+            &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
   }
   else
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       jj = RSD(j);
@@ -3876,27 +3908,27 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
         //! Use inference flag to remap mvs/references
-        p->mv[LIST_0][j][i][0]=fs->mv[LIST_0][j][i][0];
-        p->mv[LIST_0][j][i][1]=fs->mv[LIST_0][j][i][1];
-        p->mv[LIST_1][j][i][0]=fs->mv[LIST_1][j][i][0];
-        p->mv[LIST_1][j][i][1]=fs->mv[LIST_1][j][i][1];
+        ftype->mv[LIST_0][j][i][0]=fs->motion.mv[LIST_0][j][i][0];
+        ftype->mv[LIST_0][j][i][1]=fs->motion.mv[LIST_0][j][i][1];
+        ftype->mv[LIST_1][j][i][0]=fs->motion.mv[LIST_1][j][i][0];
+        ftype->mv[LIST_1][j][i][1]=fs->motion.mv[LIST_1][j][i][1];
 
-        p->ref_idx[LIST_0][j][i]=fs->ref_idx[LIST_0][j][i];
-        p->ref_idx[LIST_1][j][i]=fs->ref_idx[LIST_1][j][i];
-        p->ref_pic_id[LIST_0][j][i] = fs->ref_id[LIST_0][j][i];
-        p->ref_pic_id[LIST_1][j][i] = fs->ref_id[LIST_1][j][i];
+        ftype->ref_idx[LIST_0][j][i]=fs->motion.ref_idx[LIST_0][j][i];
+        ftype->ref_idx[LIST_1][j][i]=fs->motion.ref_idx[LIST_1][j][i];
+        ftype->ref_pic_id[LIST_0][j][i] = fs->motion.ref_id[LIST_0][j][i];
+        ftype->ref_pic_id[LIST_1][j][i] = fs->motion.ref_id[LIST_1][j][i];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]=
+          ftype->moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((ftype->ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((ftype->ref_idx[LIST_0][j][i] == -1)
+            &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
@@ -3905,19 +3937,20 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 
   if (img->direct_spatial_mv_pred_flag ==0)
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
-        if ((!img->MbaffFrameFlag &&!img->structure && fs->field_frame[j][i]) || (img->MbaffFrameFlag && fs->field_frame[j][i]))
+        if ((!img->MbaffFrameFlag &&!img->structure && fs->motion.field_frame[j][i]) || (img->MbaffFrameFlag && fs->motion.field_frame[j][i]))
         {
-          p->mv[LIST_0][j][i][1] *= 2;
-          p->mv[LIST_1][j][i][1] *= 2;
+          ftype->mv[LIST_0][j][i][1] *= 2;
+          ftype->mv[LIST_1][j][i][1] *= 2;
         }
-        else  if (img->structure && !fs->field_frame[j][i])
+        else  if (img->structure && !fs->motion.field_frame[j][i])
         {
-          p->mv[LIST_0][j][i][1] /= 2;
-          p->mv[LIST_1][j][i][1] /= 2;
+          ftype->mv[LIST_0][j][i][1] /= 2;
+          ftype->mv[LIST_1][j][i][1] /= 2;
         }
 
       }
@@ -3970,6 +4003,7 @@ void compute_colocated(ColocatedParams* p, StorablePicture **listX[6])
 void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 {
   StorablePicture *fs, *fs_top, *fs_bottom;
+  MotionParams *ftype;
   int i,j, ii, jj, jdiv;
   int np = img->colour_plane_id;
 
@@ -4000,6 +4034,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
   if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       jdiv = j/2;
@@ -4007,7 +4042,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
 
-        if (img->MbaffFrameFlag && fs->field_frame[j][i])
+        if (img->MbaffFrameFlag && fs->motion.field_frame[j][i])
         {
           //! Assign frame buffers for field MBs
           //! Check whether we should use top or bottom field mvs.
@@ -4015,41 +4050,41 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
           if (iabs(enc_picture->poc - fs_bottom->poc) > iabs(enc_picture->poc - fs_top->poc) )
           {
-            p->mv[LIST_0][j][i][0]    = fs_top->mv_JV[np][LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]    = fs_top->mv_JV[np][LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]    = fs_top->mv_JV[np][LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]    = fs_top->mv_JV[np][LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]  = fs_top->ref_idx_JV[np][LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]  = fs_top->ref_idx_JV[np][LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i]   = fs->ref_id_JV[np][LIST_0][jj][i];
-            p->ref_pic_id[LIST_1][j][i]   = fs->ref_id_JV[np][LIST_1][jj][i];
+            ftype->mv[LIST_0][j][i][0]    = fs_top->JVmotion[np].mv[LIST_0][jdiv][i][0];
+            ftype->mv[LIST_0][j][i][1]    = fs_top->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+            ftype->mv[LIST_1][j][i][0]    = fs_top->JVmotion[np].mv[LIST_1][jdiv][i][0];
+            ftype->mv[LIST_1][j][i][1]    = fs_top->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+            ftype->ref_idx[LIST_0][j][i]  = fs_top->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+            ftype->ref_idx[LIST_1][j][i]  = fs_top->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+            ftype->ref_pic_id[LIST_0][j][i]   = fs->JVmotion[np].ref_id[LIST_0][jj][i];
+            ftype->ref_pic_id[LIST_1][j][i]   = fs->JVmotion[np].ref_id[LIST_1][jj][i];
 
             p->is_long_term             = fs_top->is_long_term;
           }
           else
           {
-            p->mv[LIST_0][j][i][0]      = fs_bottom->mv_JV[np][LIST_0][jdiv][i][0];
-            p->mv[LIST_0][j][i][1]      = fs_bottom->mv_JV[np][LIST_0][jdiv][i][1] ;
-            p->mv[LIST_1][j][i][0]      = fs_bottom->mv_JV[np][LIST_1][jdiv][i][0];
-            p->mv[LIST_1][j][i][1]      = fs_bottom->mv_JV[np][LIST_1][jdiv][i][1] ;
-            p->ref_idx[LIST_0][j][i]    = fs_bottom->ref_idx_JV[np][LIST_0][jdiv][i];
-            p->ref_idx[LIST_1][j][i]    = fs_bottom->ref_idx_JV[np][LIST_1][jdiv][i];
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][jj + 4][i];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][jj + 4][i];
+            ftype->mv[LIST_0][j][i][0]      = fs_bottom->JVmotion[np].mv[LIST_0][jdiv][i][0];
+            ftype->mv[LIST_0][j][i][1]      = fs_bottom->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+            ftype->mv[LIST_1][j][i][0]      = fs_bottom->JVmotion[np].mv[LIST_1][jdiv][i][0];
+            ftype->mv[LIST_1][j][i][1]      = fs_bottom->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+            ftype->ref_idx[LIST_0][j][i]    = fs_bottom->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+            ftype->ref_idx[LIST_1][j][i]    = fs_bottom->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+            ftype->ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][jj + 4][i];
+            ftype->ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][jj + 4][i];
 
             p->is_long_term             = fs_bottom->is_long_term;
           }
         }
         else
         {
-          p->mv[LIST_0][j][i][0]      = fs->mv_JV[np][LIST_0][j][i][0];
-          p->mv[LIST_0][j][i][1]      = fs->mv_JV[np][LIST_0][j][i][1] ;
-          p->mv[LIST_1][j][i][0]      = fs->mv_JV[np][LIST_1][j][i][0];
-          p->mv[LIST_1][j][i][1]      = fs->mv_JV[np][LIST_1][j][i][1] ;
-          p->ref_idx[LIST_0][j][i]    = fs->ref_idx_JV[np][LIST_0][j][i];
-          p->ref_idx[LIST_1][j][i]    = fs->ref_idx_JV[np][LIST_1][j][i];
-          p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][j][i];
-          p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][j][i];
+          ftype->mv[LIST_0][j][i][0]      = fs->JVmotion[np].mv[LIST_0][j][i][0];
+          ftype->mv[LIST_0][j][i][1]      = fs->JVmotion[np].mv[LIST_0][j][i][1] ;
+          ftype->mv[LIST_1][j][i][0]      = fs->JVmotion[np].mv[LIST_1][j][i][0];
+          ftype->mv[LIST_1][j][i][1]      = fs->JVmotion[np].mv[LIST_1][j][i][1] ;
+          ftype->ref_idx[LIST_0][j][i]    = fs->JVmotion[np].ref_idx[LIST_0][j][i];
+          ftype->ref_idx[LIST_1][j][i]    = fs->JVmotion[np].ref_idx[LIST_1][j][i];
+          ftype->ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][j][i];
+          ftype->ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][j][i];
 
           p->is_long_term             = fs->is_long_term;
         }
@@ -4061,6 +4096,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
   //! Generate field MVs from Frame MVs
   if (img->structure || img->MbaffFrameFlag)
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/8 ; j++)
     {
       jj = RSD(j);
@@ -4070,102 +4106,102 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
         //! Do nothing if macroblock as field coded in MB-AFF
         if (!img->MbaffFrameFlag )
         {
-          p->mv[LIST_0][j][i][0] = fs->mv_JV[np][LIST_0][jj][ii][0];
-          p->mv[LIST_0][j][i][1] = fs->mv_JV[np][LIST_0][jj][ii][1];
-          p->mv[LIST_1][j][i][0] = fs->mv_JV[np][LIST_1][jj][ii][0];
-          p->mv[LIST_1][j][i][1] = fs->mv_JV[np][LIST_1][jj][ii][1];
+          ftype->mv[LIST_0][j][i][0] = fs->JVmotion[np].mv[LIST_0][jj][ii][0];
+          ftype->mv[LIST_0][j][i][1] = fs->JVmotion[np].mv[LIST_0][jj][ii][1];
+          ftype->mv[LIST_1][j][i][0] = fs->JVmotion[np].mv[LIST_1][jj][ii][0];
+          ftype->mv[LIST_1][j][i][1] = fs->JVmotion[np].mv[LIST_1][jj][ii][1];
 
           // Scaling of references is done here since it will not affect spatial direct (2*0 =0)
 
-          if (fs->ref_idx[LIST_0][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_0][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_0][j][i] = -1;
-            p->ref_pic_id[LIST_0][j][i] = -1;
+            ftype->ref_idx   [LIST_0][j][i] = -1;
+            ftype->ref_pic_id[LIST_0][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_0][j][i] = fs->ref_idx_JV[np][LIST_0][jj][ii] ;
-            p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV [np][LIST_0][jj][ii];
+            ftype->ref_idx   [LIST_0][j][i] = fs->JVmotion[np].ref_idx[LIST_0][jj][ii] ;
+            ftype->ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][jj][ii];
           }
 
-          if (fs->ref_idx[LIST_1][jj][ii] == -1)
+          if (fs->motion.ref_idx[LIST_1][jj][ii] == -1)
           {
-            p->ref_idx   [LIST_1][j][i] = -1;
-            p->ref_pic_id[LIST_1][j][i] = -1;
+            ftype->ref_idx   [LIST_1][j][i] = -1;
+            ftype->ref_pic_id[LIST_1][j][i] = -1;
           }
           else
           {
-            p->ref_idx   [LIST_1][j][i] = fs->ref_idx_JV[np][LIST_1][jj][ii];
-            p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV [np][LIST_1][jj][ii];
+            ftype->ref_idx   [LIST_1][j][i] = fs->JVmotion[np].ref_idx[LIST_1][jj][ii];
+            ftype->ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][jj][ii];
           }
 
           p->is_long_term = fs->is_long_term;
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->moving_block[j][i] =
+            ftype->moving_block[j][i] =
               !((!p->is_long_term
-              && ((p->ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->ref_idx[LIST_0][j][i] == -1)
-              &&  (p->ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((ftype->ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((ftype->ref_idx[LIST_0][j][i] == -1)
+              &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
           }
         }
         else
         {
-          p->bottom_mv[LIST_0][j][i][0] = fs_bottom->mv_JV[np][LIST_0][jj][ii][0];
-          p->bottom_mv[LIST_0][j][i][1] = fs_bottom->mv_JV[np][LIST_0][jj][ii][1];
-          p->bottom_mv[LIST_1][j][i][0] = fs_bottom->mv_JV[np][LIST_1][jj][ii][0];
-          p->bottom_mv[LIST_1][j][i][1] = fs_bottom->mv_JV[np][LIST_1][jj][ii][1];
-          p->bottom_ref_idx[LIST_0][j][i] = fs_bottom->ref_idx_JV[np][LIST_0][jj][ii];
-          p->bottom_ref_idx[LIST_1][j][i] = fs_bottom->ref_idx_JV[np][LIST_1][jj][ii];
-          p->bottom_ref_pic_id[LIST_0][j][i] = fs_bottom->ref_id_JV[np][LIST_0][jj][ii];
-          p->bottom_ref_pic_id[LIST_1][j][i] = fs_bottom->ref_id_JV[np][LIST_1][jj][ii];
+          p->bottom.mv[LIST_0][j][i][0] = fs_bottom->JVmotion[np].mv[LIST_0][jj][ii][0];
+          p->bottom.mv[LIST_0][j][i][1] = fs_bottom->JVmotion[np].mv[LIST_0][jj][ii][1];
+          p->bottom.mv[LIST_1][j][i][0] = fs_bottom->JVmotion[np].mv[LIST_1][jj][ii][0];
+          p->bottom.mv[LIST_1][j][i][1] = fs_bottom->JVmotion[np].mv[LIST_1][jj][ii][1];
+          p->bottom.ref_idx[LIST_0][j][i] = fs_bottom->JVmotion[np].ref_idx[LIST_0][jj][ii];
+          p->bottom.ref_idx[LIST_1][j][i] = fs_bottom->JVmotion[np].ref_idx[LIST_1][jj][ii];
+          p->bottom.ref_pic_id[LIST_0][j][i] = fs_bottom->JVmotion[np].ref_id[LIST_0][jj][ii];
+          p->bottom.ref_pic_id[LIST_1][j][i] = fs_bottom->JVmotion[np].ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->bottom_moving_block[j][i] =
+            p->bottom.moving_block[j][i] =
               !((!fs_bottom->is_long_term
-              && ((p->bottom_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->bottom_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->bottom_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->bottom_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->bottom.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->bottom.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->bottom.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->bottom.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          p->top_mv[LIST_0][j][i][0] = fs_top->mv_JV[np][LIST_0][jj][ii][0];
-          p->top_mv[LIST_0][j][i][1] = fs_top->mv_JV[np][LIST_0][jj][ii][1];
-          p->top_mv[LIST_1][j][i][0] = fs_top->mv_JV[np][LIST_1][jj][ii][0];
-          p->top_mv[LIST_1][j][i][1] = fs_top->mv_JV[np][LIST_1][jj][ii][1];
-          p->top_ref_idx[LIST_0][j][i] = fs_top->ref_idx_JV[np][LIST_0][jj][ii];
-          p->top_ref_idx[LIST_1][j][i] = fs_top->ref_idx_JV[np][LIST_1][jj][ii];
-          p->top_ref_pic_id[LIST_0][j][i] = fs_top->ref_id_JV[np][LIST_0][jj][ii];
-          p->top_ref_pic_id[LIST_1][j][i] = fs_top->ref_id_JV[np][LIST_1][jj][ii];
+          p->top.mv[LIST_0][j][i][0] = fs_top->JVmotion[np].mv[LIST_0][jj][ii][0];
+          p->top.mv[LIST_0][j][i][1] = fs_top->JVmotion[np].mv[LIST_0][jj][ii][1];
+          p->top.mv[LIST_1][j][i][0] = fs_top->JVmotion[np].mv[LIST_1][jj][ii][0];
+          p->top.mv[LIST_1][j][i][1] = fs_top->JVmotion[np].mv[LIST_1][jj][ii][1];
+          p->top.ref_idx[LIST_0][j][i] = fs_top->JVmotion[np].ref_idx[LIST_0][jj][ii];
+          p->top.ref_idx[LIST_1][j][i] = fs_top->JVmotion[np].ref_idx[LIST_1][jj][ii];
+          p->top.ref_pic_id[LIST_0][j][i] = fs_top->JVmotion[np].ref_id[LIST_0][jj][ii];
+          p->top.ref_pic_id[LIST_1][j][i] = fs_top->JVmotion[np].ref_id[LIST_1][jj][ii];
 
           if (img->direct_spatial_mv_pred_flag == 1)
           {
-            p->top_moving_block[j][i] =
+            p->top.moving_block[j][i] =
               !((!fs_top->is_long_term
-              && ((p->top_ref_idx[LIST_0][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_0][j][i][1])>>1 == 0)))
-              || ((p->top_ref_idx[LIST_0][j][i] == -1)
-              &&  (p->top_ref_idx[LIST_1][j][i] == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][0])>>1 == 0)
-              &&  (iabs(p->top_mv[LIST_1][j][i][1])>>1 == 0)));
+              && ((p->top.ref_idx[LIST_0][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_0][j][i][1])>>1 == 0)))
+              || ((p->top.ref_idx[LIST_0][j][i] == -1)
+              &&  (p->top.ref_idx[LIST_1][j][i] == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][0])>>1 == 0)
+              &&  (iabs(p->top.mv[LIST_1][j][i][1])>>1 == 0)));
           }
 
-          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->field_frame[2*j][i])
+          if ((img->direct_spatial_mv_pred_flag == 0 ) && !fs->motion.field_frame[2*j][i])
           {
-            p->top_mv[LIST_0][j][i][1] /= 2;
-            p->top_mv[LIST_1][j][i][1] /= 2;
-            p->bottom_mv[LIST_0][j][i][1] /= 2;
-            p->bottom_mv[LIST_1][j][i][1] /= 2;
+            p->top.mv[LIST_0][j][i][1] /= 2;
+            p->top.mv[LIST_1][j][i][1] /= 2;
+            p->bottom.mv[LIST_0][j][i][1] /= 2;
+            p->bottom.mv[LIST_1][j][i][1] /= 2;
           }
 
         }
@@ -4181,6 +4217,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
     if (!img->structure)
     {
+      ftype = &p->frame;
       for (j=0 ; j < (fs->size_y>>2) ; j++)
       {
         jdiv = j>>1;
@@ -4188,32 +4225,32 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
         for (i=0 ; i < (fs->size_x>>2) ; i++)
         {
 
-          if (fs->field_frame[j][i])
+          if (fs->motion.field_frame[j][i])
           {
             if (iabs(enc_picture->poc - fs->bottom_field->poc) > iabs(enc_picture->poc - fs->top_field->poc))
             {
-              p->mv[LIST_0][j][i][0] = fs->top_field->mv_JV[np][LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->top_field->mv_JV[np][LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->top_field->mv_JV[np][LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->top_field->mv_JV[np][LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->top_field->ref_idx_JV[np][LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->top_field->ref_idx_JV[np][LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i]   = fs->ref_id_JV[np][LIST_0][jj][i];
-              p->ref_pic_id[LIST_1][j][i]   = fs->ref_id_JV[np][LIST_1][jj][i];
+              ftype->mv[LIST_0][j][i][0] = fs->top_field->JVmotion[np].mv[LIST_0][jdiv][i][0];
+              ftype->mv[LIST_0][j][i][1] = fs->top_field->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+              ftype->mv[LIST_1][j][i][0] = fs->top_field->JVmotion[np].mv[LIST_1][jdiv][i][0];
+              ftype->mv[LIST_1][j][i][1] = fs->top_field->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+
+              ftype->ref_idx[LIST_0][j][i]  = fs->top_field->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+              ftype->ref_idx[LIST_1][j][i]  = fs->top_field->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+              ftype->ref_pic_id[LIST_0][j][i]   = fs->JVmotion[np].ref_id[LIST_0][jj][i];
+              ftype->ref_pic_id[LIST_1][j][i]   = fs->JVmotion[np].ref_id[LIST_1][jj][i];
               p->is_long_term               = fs->top_field->is_long_term;
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = fs->bottom_field->mv_JV[np][LIST_0][jdiv][i][0];
-              p->mv[LIST_0][j][i][1] = fs->bottom_field->mv_JV[np][LIST_0][jdiv][i][1] ;
-              p->mv[LIST_1][j][i][0] = fs->bottom_field->mv_JV[np][LIST_1][jdiv][i][0];
-              p->mv[LIST_1][j][i][1] = fs->bottom_field->mv_JV[np][LIST_1][jdiv][i][1] ;
-
-              p->ref_idx[LIST_0][j][i]  = fs->bottom_field->ref_idx_JV[np][LIST_0][jdiv][i];
-              p->ref_idx[LIST_1][j][i]  = fs->bottom_field->ref_idx_JV[np][LIST_1][jdiv][i];
-              p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][jj + 4][i];
-              p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][jj + 4][i];
+              ftype->mv[LIST_0][j][i][0] = fs->bottom_field->JVmotion[np].mv[LIST_0][jdiv][i][0];
+              ftype->mv[LIST_0][j][i][1] = fs->bottom_field->JVmotion[np].mv[LIST_0][jdiv][i][1] ;
+              ftype->mv[LIST_1][j][i][0] = fs->bottom_field->JVmotion[np].mv[LIST_1][jdiv][i][0];
+              ftype->mv[LIST_1][j][i][1] = fs->bottom_field->JVmotion[np].mv[LIST_1][jdiv][i][1] ;
+
+              ftype->ref_idx[LIST_0][j][i]  = fs->bottom_field->JVmotion[np].ref_idx[LIST_0][jdiv][i];
+              ftype->ref_idx[LIST_1][j][i]  = fs->bottom_field->JVmotion[np].ref_idx[LIST_1][jdiv][i];
+              ftype->ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][jj + 4][i];
+              ftype->ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][jj + 4][i];
               p->is_long_term             = fs->bottom_field->is_long_term;
             }
           }
@@ -4227,6 +4264,7 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
   if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
   {
+    ftype = &p->frame;
     for (j=0 ; j < (fs->size_y>>2) ; j++)
     {
       jj = RSD(j);
@@ -4234,33 +4272,34 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
 
-        p->mv[LIST_0][j][i][0]=p->mv[LIST_0][jj][ii][0];
-        p->mv[LIST_0][j][i][1]=p->mv[LIST_0][jj][ii][1];
-        p->mv[LIST_1][j][i][0]=p->mv[LIST_1][jj][ii][0];
-        p->mv[LIST_1][j][i][1]=p->mv[LIST_1][jj][ii][1];
+        ftype->mv[LIST_0][j][i][0]=ftype->mv[LIST_0][jj][ii][0];
+        ftype->mv[LIST_0][j][i][1]=ftype->mv[LIST_0][jj][ii][1];
+        ftype->mv[LIST_1][j][i][0]=ftype->mv[LIST_1][jj][ii][0];
+        ftype->mv[LIST_1][j][i][1]=ftype->mv[LIST_1][jj][ii][1];
 
-        p->ref_idx[LIST_0][j][i]=p->ref_idx[LIST_0][jj][ii];
-        p->ref_idx[LIST_1][j][i]=p->ref_idx[LIST_1][jj][ii];
-        p->ref_pic_id[LIST_0][j][i] = p->ref_pic_id[LIST_0][jj][ii];
-        p->ref_pic_id[LIST_1][j][i] = p->ref_pic_id[LIST_1][jj][ii];
+        ftype->ref_idx[LIST_0][j][i]=ftype->ref_idx[LIST_0][jj][ii];
+        ftype->ref_idx[LIST_1][j][i]=ftype->ref_idx[LIST_1][jj][ii];
+        ftype->ref_pic_id[LIST_0][j][i] = ftype->ref_pic_id[LIST_0][jj][ii];
+        ftype->ref_pic_id[LIST_1][j][i] = ftype->ref_pic_id[LIST_1][jj][ii];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]=
+          ftype->moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((ftype->ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((ftype->ref_idx[LIST_0][j][i] == -1)
+            &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
   }
   else
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       jj = RSD(j);
@@ -4268,27 +4307,27 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
       {
         ii = RSD(i);
         //! Use inference flag to remap mvs/references
-        p->mv[LIST_0][j][i][0]=fs->mv_JV[np][LIST_0][j][i][0];
-        p->mv[LIST_0][j][i][1]=fs->mv_JV[np][LIST_0][j][i][1];
-        p->mv[LIST_1][j][i][0]=fs->mv_JV[np][LIST_1][j][i][0];
-        p->mv[LIST_1][j][i][1]=fs->mv_JV[np][LIST_1][j][i][1];
+        ftype->mv[LIST_0][j][i][0]=fs->JVmotion[np].mv[LIST_0][j][i][0];
+        ftype->mv[LIST_0][j][i][1]=fs->JVmotion[np].mv[LIST_0][j][i][1];
+        ftype->mv[LIST_1][j][i][0]=fs->JVmotion[np].mv[LIST_1][j][i][0];
+        ftype->mv[LIST_1][j][i][1]=fs->JVmotion[np].mv[LIST_1][j][i][1];
 
-        p->ref_idx[LIST_0][j][i]=fs->ref_idx_JV[np][LIST_0][j][i];
-        p->ref_idx[LIST_1][j][i]=fs->ref_idx_JV[np][LIST_1][j][i];
-        p->ref_pic_id[LIST_0][j][i] = fs->ref_id_JV[np][LIST_0][j][i];
-        p->ref_pic_id[LIST_1][j][i] = fs->ref_id_JV[np][LIST_1][j][i];
+        ftype->ref_idx[LIST_0][j][i]=fs->JVmotion[np].ref_idx[LIST_0][j][i];
+        ftype->ref_idx[LIST_1][j][i]=fs->JVmotion[np].ref_idx[LIST_1][j][i];
+        ftype->ref_pic_id[LIST_0][j][i] = fs->JVmotion[np].ref_id[LIST_0][j][i];
+        ftype->ref_pic_id[LIST_1][j][i] = fs->JVmotion[np].ref_id[LIST_1][j][i];
 
         if (img->direct_spatial_mv_pred_flag == 1)
         {
-          p->moving_block[j][i]=
+          ftype->moving_block[j][i]=
             !((!p->is_long_term
-            && ((p->ref_idx[LIST_0][j][i] == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_0][j][i][1])>>1 == 0)))
-            || ((p->ref_idx[LIST_0][j][i] == -1)
-            &&  (p->ref_idx[LIST_1][j][i] == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][0])>>1 == 0)
-            &&  (iabs(p->mv[LIST_1][j][i][1])>>1 == 0)));
+            && ((ftype->ref_idx[LIST_0][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_0][j][i][1])>>1 == 0)))
+            || ((ftype->ref_idx[LIST_0][j][i] == -1)
+            &&  (ftype->ref_idx[LIST_1][j][i] == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][0])>>1 == 0)
+            &&  (iabs(ftype->mv[LIST_1][j][i][1])>>1 == 0)));
         }
       }
     }
@@ -4297,19 +4336,20 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
 
   if (img->direct_spatial_mv_pred_flag ==0)
   {
+    ftype = &p->frame;
     for (j=0 ; j<fs->size_y/4 ; j++)
     {
       for (i=0 ; i<fs->size_x/4 ; i++)
       {
-        if ((!img->MbaffFrameFlag &&!img->structure && fs->field_frame[j][i]) || (img->MbaffFrameFlag && fs->field_frame[j][i]))
+        if ((!img->MbaffFrameFlag &&!img->structure && fs->motion.field_frame[j][i]) || (img->MbaffFrameFlag && fs->motion.field_frame[j][i]))
         {
-          p->mv[LIST_0][j][i][1] *= 2;
-          p->mv[LIST_1][j][i][1] *= 2;
+          ftype->mv[LIST_0][j][i][1] *= 2;
+          ftype->mv[LIST_1][j][i][1] *= 2;
         }
-        else  if (img->structure && !fs->field_frame[j][i])
+        else  if (img->structure && !fs->motion.field_frame[j][i])
         {
-          p->mv[LIST_0][j][i][1] /= 2;
-          p->mv[LIST_1][j][i][1] /= 2;
+          ftype->mv[LIST_0][j][i][1] /= 2;
+          ftype->mv[LIST_1][j][i][1] /= 2;
         }
 
       }
@@ -4360,44 +4400,15 @@ void compute_colocated_JV(ColocatedParams* p, StorablePicture **listX[6])
  */
 void copy_storable_param_JV( int nplane, StorablePicture *d, StorablePicture *s )
 {
-  int np, ny, nx;
-
   // copy ref_idx
-  for( np=0; np<2; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_idx_JV[nplane][np][ny], s->ref_idx[np][ny], sizeof(byte)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  memcpy( d->JVmotion[nplane].ref_idx[0][0], s->motion.ref_idx[0][0], 2 * (img->height/BLOCK_SIZE) * (img->width/BLOCK_SIZE) * sizeof(byte) );
 
   // copy ref_pic_id
-  for( np=0; np<6; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_pic_id_JV[nplane][np][ny], s->ref_pic_id[np][ny], sizeof(int64)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  memcpy( d->JVmotion[nplane].ref_pic_id[0][0], s->motion.ref_pic_id[0][0], 6 * (img->height/BLOCK_SIZE) * (img->width/BLOCK_SIZE) * sizeof(int64) );
 
-  // copy ref_id
-  for( np=0; np<6; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      memcpy( d->ref_id_JV[nplane][np][ny], s->ref_id[np][ny], sizeof(int64)*(img->width/BLOCK_SIZE) );
-    }
-  }
+  // copy motion.ref_id
+  memcpy( d->JVmotion[nplane].ref_id[0][0], s->motion.ref_id[0][0], 6 * (img->width/BLOCK_SIZE) * (img->height/BLOCK_SIZE) * sizeof(int64));
 
   // copy mv
-  for( np=0; np<2; np++ )
-  {
-    for( ny=0; ny<img->height/BLOCK_SIZE; ny++ )
-    {
-      for( nx=0; nx<img->width/BLOCK_SIZE; nx++ )
-      {
-        memcpy( d->mv_JV[nplane][np][ny][nx], s->mv[np][ny][nx], sizeof(short)*2 );
-      }
-    }
-  }
+  memcpy( d->JVmotion[nplane].mv[0][0][0], s->motion.mv[0][0][0], 2 * img->height/BLOCK_SIZE * img->width/BLOCK_SIZE * sizeof(short)*2 );
 }
diff --git a/lencod/src/mc_prediction.c b/lencod/src/mc_prediction.c
index 2aa6e42..7fac0c6 100644
--- a/lencod/src/mc_prediction.c
+++ b/lencod/src/mc_prediction.c
@@ -146,7 +146,8 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
                      int   l0_mode,     //!< list0 prediction mode (1-7, 0=DIRECT if l1_mode=0)
                      int   l1_mode,     //!< list1 prediction mode (1-7, 0=DIRECT if l0_mode=0)
                      short l0_ref_idx,  //!< reference frame for list0 prediction (-1: Intra4x4 pred. with l0_mode)
-                     short l1_ref_idx   //!< reference frame for list1 prediction 
+                     short l1_ref_idx,   //!< reference frame for list1 prediction 
+                     short bipred_me     //!< use bi prediction mv (0=no bipred, 1 = use set 1, 2 = use set 2)
                      )
 {
   int  i, j;
@@ -160,13 +161,13 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
   imgpel* l1pred    = l1_pred;  
   short****** mv_array = img->all_mv;
   short   *curr_mv = NULL;
-  imgpel (*curr_mpr)[16] = img->mpr[0];
+  imgpel (*mb_pred)[16] = img->mb_pred[0];
 
   int  apply_weights = ( (active_pps->weighted_pred_flag  && (img->type== P_SLICE || img->type == SP_SLICE)) ||
     (active_pps->weighted_bipred_idc && (img->type== B_SLICE)));
 
-  if (currMB->bi_pred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && l0_mode==1 && l1_mode==1)
-    mv_array = currMB->bi_pred_me == 1? img->bipred_mv1 : img->bipred_mv2;
+  if (bipred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && is_bipred_enabled(l0_mode) && is_bipred_enabled(l1_mode))
+    mv_array = img->bipred_mv[bipred_me - 1]; 
 
   switch (p_dir)
   {
@@ -199,7 +200,7 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
       int weight_denom = luma_log_weight_denom + 1;
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)  
-          curr_mpr[j][i] = iClip1( img->max_imgpel_value, 
+          mb_pred[j][i] = iClip1( img->max_imgpel_value, 
           ((wbp0 * *l0pred++ + wbp1 * *l1pred++ + wp_round) >> (weight_denom)) + offset); 
     }
     else if (p_dir==0)
@@ -208,7 +209,7 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
       int offset = wp_offset[0][l0_ref_idx][0];
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( img->max_imgpel_value, 
+          mb_pred[j][i] = iClip1( img->max_imgpel_value, 
           ((wp * *l0pred++  + wp_luma_round) >> luma_log_weight_denom) + offset);
     }
     else // (p_dir==1)
@@ -217,7 +218,7 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
       int offset = wp_offset[1][l1_ref_idx][0];
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( img->max_imgpel_value, 
+          mb_pred[j][i] = iClip1( img->max_imgpel_value, 
           ((wp * *l1pred++  + wp_luma_round) >> luma_log_weight_denom) + offset );
     }
   }
@@ -227,13 +228,13 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
     {
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
+          mb_pred[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
     }
     else if (p_dir==0)
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l0pred, block_size_x * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l0pred, block_size_x * sizeof(imgpel));
         l0pred += block_size_x;
       }
     }
@@ -241,7 +242,7 @@ void LumaPrediction ( Macroblock* currMB,//!< Current Macroblock
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l1pred, block_size_x * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l1pred, block_size_x * sizeof(imgpel));
         l1pred += block_size_x;
       }
     }
@@ -278,10 +279,10 @@ void LumaPredictionBi ( Macroblock* currMB, //!< Current Macroblock
 
   int  apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
     (active_pps->weighted_bipred_idc && (img->type == B_SLICE)));  
-  short   ******mv_array = list ? img->bipred_mv1 : img->bipred_mv2;
+  short   ******mv_array = img->bipred_mv[list]; 
   short   *mv_arrayl0 = mv_array[LIST_0][l0_ref_idx][l0_mode][by][bx];
   short   *mv_arrayl1 = mv_array[LIST_1][l1_ref_idx][l1_mode][by][bx];
-  imgpel (*curr_mpr)[16] = img->mpr[0];
+  imgpel (*mb_pred)[16] = img->mb_pred[0];
 
   OneComponentLumaPrediction (l0_pred, pic_opix_x + mv_arrayl0[0], pic_opix_y + mv_arrayl0[1], block_size_x, block_size_y, listX[0+currMB->list_offset][l0_ref_idx]);
   OneComponentLumaPrediction (l1_pred, pic_opix_x + mv_arrayl1[0], pic_opix_y + mv_arrayl1[1], block_size_x, block_size_y, listX[1+currMB->list_offset][l1_ref_idx]);
@@ -296,14 +297,14 @@ void LumaPredictionBi ( Macroblock* currMB, //!< Current Macroblock
 
     for   (j=block_y; j<block_y4; j++)
       for (i=block_x; i<block_x4; i++)
-        curr_mpr[j][i] = iClip1( img->max_imgpel_value,
+        mb_pred[j][i] = iClip1( img->max_imgpel_value,
         ((wbp0 * *l0pred++ + wbp1 * *l1pred++ + wp_round) >> weight_denom) + offset);
   }
   else
   {
     for   (j=block_y; j<block_y4; j++)
       for (i=block_x; i<block_x4; i++)
-        curr_mpr[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
+        mb_pred[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
   }
 }
 
@@ -477,12 +478,12 @@ void IntraChromaPrediction4x4 (Macroblock* currMB, //! <-- Current Macroblock
                                int  block_y)       //! <-- relative vertical   block coordinate of 4x4 block
 {
   int j;
-  imgpel (*curr_mpr)[16]       = img->mpr[ uv ];
+  imgpel (*mb_pred)[16]       = img->mb_pred[ uv ];
   imgpel (*curr_mpr_16x16)[16] = img->mpr_16x16[uv][currMB->c_ipred_mode];
 
   //===== prediction =====
   for (j=block_y; j<block_y + BLOCK_SIZE; j++)
-    memcpy(&curr_mpr[j][block_x],&curr_mpr_16x16[j][block_x], BLOCK_SIZE * sizeof(imgpel));
+    memcpy(&mb_pred[j][block_x],&curr_mpr_16x16[j][block_x], BLOCK_SIZE * sizeof(imgpel));
 }
 
 /*!
@@ -501,7 +502,9 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
                        int   l0_mode,       // <-- list0  prediction mode (1-7, 0=DIRECT if l1_mode=0)
                        int   l1_mode,       // <-- list1 prediction mode (1-7, 0=DIRECT if l0_mode=0)
                        short l0_ref_idx,    // <-- reference frame for list0 prediction (if (<0) -> intra prediction)
-                       short l1_ref_idx)    // <-- reference frame for list1 prediction 
+                       short l1_ref_idx,    // <-- reference frame for list1 prediction 
+                       short bipred_me      // <-- use bi prediction mv (0=no bipred, 1 = use set 1, 2 = use set 2)
+                       )    
 {
   int  i, j;
   int  block_x4     = block_x + block_size_x;
@@ -515,13 +518,13 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
   short****** mv_array = img->all_mv;    
   int max_imgpel_value_uv = img->max_imgpel_value_comp[1];
   int uv_comp = uv + 1;
-  imgpel (*curr_mpr)[16] = img->mpr[ uv_comp];
+  imgpel (*mb_pred)[16] = img->mb_pred[ uv_comp];
 
   int  apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
     (active_pps->weighted_bipred_idc && (img->type == B_SLICE)));
 
-  if (currMB->bi_pred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && l0_mode==1 && l1_mode==1)
-    mv_array = currMB->bi_pred_me == 1? img->bipred_mv1 : img->bipred_mv2;
+  if (bipred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && is_bipred_enabled(l0_mode)  && is_bipred_enabled(l1_mode))
+    mv_array = img->bipred_mv[bipred_me - 1]; 
 
   //===== INTRA PREDICTION =====
   if (p_dir==-1)
@@ -560,7 +563,7 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
 
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] =  iClip1( max_imgpel_value_uv,
+          mb_pred[j][i] =  iClip1( max_imgpel_value_uv,
           ((wbp0 * *l0pred++ + wbp1 * *l1pred++ + wp_round) >> (weight_denom)) + (offset) );
     }
     else if (p_dir==0)
@@ -569,7 +572,7 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
       int offset = wp_offset[0][l0_ref_idx][uv_comp];
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( max_imgpel_value_uv, (( wp * *l0pred++ + wp_chroma_round) >> chroma_log_weight_denom) +  offset);
+          mb_pred[j][i] = iClip1( max_imgpel_value_uv, (( wp * *l0pred++ + wp_chroma_round) >> chroma_log_weight_denom) +  offset);
     }
     else // (p_dir==1)
     {
@@ -578,7 +581,7 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
 
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( max_imgpel_value_uv, ((wp * *l1pred++ + wp_chroma_round) >> chroma_log_weight_denom) + offset);
+          mb_pred[j][i] = iClip1( max_imgpel_value_uv, ((wp * *l1pred++ + wp_chroma_round) >> chroma_log_weight_denom) + offset);
     }
   }
   else
@@ -587,13 +590,13 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
     {
       for   (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
+          mb_pred[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
     }
     else if (p_dir==0)
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l0pred, block_size_x * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l0pred, block_size_x * sizeof(imgpel));
         l0pred += block_size_x;
       }
     }
@@ -601,7 +604,7 @@ void ChromaPrediction ( Macroblock* currMB, // <-- Current Macroblock
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l1pred, block_size_x * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l1pred, block_size_x * sizeof(imgpel));
         l1pred += block_size_x;
       }
     }
@@ -624,7 +627,9 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
                            int   l0_mode,      // <-- list0  prediction mode (1-7, 0=DIRECT if l1_mode=0)
                            int   l1_mode,      // <-- list1 prediction mode (1-7, 0=DIRECT if l0_mode=0)
                            short l0_ref_idx,   // <-- reference frame for list0 prediction (if (<0) -> intra prediction)
-                           short l1_ref_idx)   // <-- reference frame for list1 prediction 
+                           short l1_ref_idx,   // <-- reference frame for list1 prediction 
+                           short bipred_me     // <-- use bi prediction mv (0=no bipred, 1 = use set 1, 2 = use set 2)
+                           )   
 {
   int  i, j;
   int  block_x4  = block_x + BLOCK_SIZE;
@@ -634,14 +639,14 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
   short****** mv_array = img->all_mv;
   int max_imgpel_value_uv = img->max_imgpel_value_comp[1];
   int uv_comp = uv + 1;
-  imgpel (*curr_mpr)[16] = img->mpr[uv_comp];
+  imgpel (*mb_pred)[16] = img->mb_pred[uv_comp];
   int     list_offset = currMB->list_offset;
 
   int  apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
     (active_pps->weighted_bipred_idc && (img->type == B_SLICE)));
 
-  if (currMB->bi_pred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && l0_mode==1 && l1_mode==1)
-    mv_array = currMB->bi_pred_me == 1? img->bipred_mv1 : img->bipred_mv2 ;
+  if (bipred_me && l0_ref_idx == 0 && l1_ref_idx == 0 && p_dir == 2 && is_bipred_enabled(l0_mode)  && is_bipred_enabled(l1_mode) )
+    mv_array = img->bipred_mv[bipred_me - 1]; 
   //===== INTRA PREDICTION =====
   if (p_dir==-1)
   {
@@ -678,7 +683,7 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
 
       for (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] =  iClip1( max_imgpel_value_uv,
+          mb_pred[j][i] =  iClip1( max_imgpel_value_uv,
           ((wbp0 * *l0pred++ + wbp1 * *l1pred++ + wp_round) >> (weight_denom)) + (offset) );
     }
     else if (p_dir==0)
@@ -687,7 +692,7 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
       int offset = wp_offset[0][l0_ref_idx][uv_comp];
       for (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( max_imgpel_value_uv, (( wp * *l0pred++ + wp_chroma_round) >> chroma_log_weight_denom) +  offset);
+          mb_pred[j][i] = iClip1( max_imgpel_value_uv, (( wp * *l0pred++ + wp_chroma_round) >> chroma_log_weight_denom) +  offset);
     }
     else // (p_dir==1)
     {
@@ -696,7 +701,7 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
 
       for (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = iClip1( max_imgpel_value_uv, ((wp * *l1pred++ + wp_chroma_round) >> chroma_log_weight_denom) + offset);
+          mb_pred[j][i] = iClip1( max_imgpel_value_uv, ((wp * *l1pred++ + wp_chroma_round) >> chroma_log_weight_denom) + offset);
     }
   }
   else
@@ -705,13 +710,13 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
     {
       for (j=block_y; j<block_y4; j++)
         for (i=block_x; i<block_x4; i++)
-          curr_mpr[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
+          mb_pred[j][i] = (*l0pred++ + *l1pred++ + 1) >> 1;
     }
     else if (p_dir==0)
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l0pred, BLOCK_SIZE * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l0pred, BLOCK_SIZE * sizeof(imgpel));
         l0pred += BLOCK_SIZE;
       }
     }
@@ -719,7 +724,7 @@ void ChromaPrediction4x4 ( Macroblock* currMB, // <-- Current Macroblock
     {
       for (j=block_y; j<block_y4; j++)
       {
-        memcpy(&(curr_mpr[j][block_x]), l1pred, BLOCK_SIZE * sizeof(imgpel));
+        memcpy(&(mb_pred[j][block_x]), l1pred, BLOCK_SIZE * sizeof(imgpel));
         l1pred += BLOCK_SIZE;
       }
     }
@@ -940,6 +945,15 @@ void IntraChromaPrediction (Macroblock *currMB, int *mb_up, int *mb_left, int*mb
     {
       getNeighbour(currMB, 0 , i, img->mb_size[IS_CHROMA], &left[i]);
     }
+
+    if ( img->MbaffFrameFlag && img->field_mode )
+    {
+      for (i=0;i<cr_MB_y;i++)
+      {
+        left[i].pos_y = left[i].pos_y >> 1;
+      }
+    }
+
     for (mode=DC_PRED_8; mode<=PLANE_8; mode++)
     {
       if ((img->type != I_SLICE || !params->IntraDisableInterOnly) && params->ChromaIntraDisable == 1 && mode!=DC_PRED_8)
@@ -951,10 +965,10 @@ void IntraChromaPrediction (Macroblock *currMB, int *mb_up, int *mb_left, int*mb
         continue;
 
       cost = 0;
-      for (uv=0; uv<2; uv++)
+      for (uv = 1; uv < 3; uv++)
       {
-        image = imgUV_org[uv];
-        curr_mpr_16x16 = img->mpr_16x16[uv + 1];
+        image = pImgOrg[uv];
+        curr_mpr_16x16 = img->mpr_16x16[uv];
         for (block_y=0; block_y<cr_MB_y; block_y+=4)
           for (block_x = 0; block_x < cr_MB_x; block_x += 4)
           {
diff --git a/lencod/src/md_high.c b/lencod/src/md_high.c
index baea43a..deb8208 100644
--- a/lencod/src/md_high.c
+++ b/lencod/src/md_high.c
@@ -25,6 +25,7 @@
 #include "me_umhexsmp.h"
 #include "macroblock.h"
 
+
 /*!
 *************************************************************************************
 * \brief
@@ -48,6 +49,7 @@ void encode_one_macroblock_high (Macroblock *currMB)
   int         mb_available_up;
   int         mb_available_left;
   int         mb_available_up_left;
+  int         best8x8l0ref, best8x8l1ref; 
 
   short       islice      = (short) (img->type==I_SLICE);
   short       bslice      = (short) (img->type==B_SLICE);
@@ -57,11 +59,13 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
   int         prev_mb_nr    = FmoGetPreviousMBNr(img->current_mb_nr);
   Macroblock* prevMB        = (prev_mb_nr >= 0) ? &img->mb_data[prev_mb_nr]:NULL ;
-  imgpel    (*curr_mpr)[16] = img->mpr[0];
+  imgpel    (*mb_pred)[16] = img->mb_pred[0];
+  Block8x8Info *b8x8info   = img->b8x8info;
 
   short   min_chroma_pred_mode, max_chroma_pred_mode;
 
-  short inter_skip = 0;
+  short   inter_skip = 0;
+  short   bipred_me = 0;
   double min_rate = 0;
 
   if(params->SearchMode == UM_HEX)
@@ -85,7 +89,6 @@ void encode_one_macroblock_high (Macroblock *currMB)
   //---------------------------------------------------
   store_coding_state (currMB, cs_cm);
 
-
   if (!intra)
   {
     //===== set direct motion vectors =====
@@ -103,8 +106,8 @@ void encode_one_macroblock_high (Macroblock *currMB)
     //===== MOTION ESTIMATION FOR 16x16, 16x8, 8x16 BLOCKS =====
     for (min_cost=INT_MAX, mode=1; mode<4; mode++)
     {
-      bi_pred_me = 0;
-      img->bi_pred_me[mode]=0;
+      bipred_me = 0;
+      b8x8info->bipred8x8me[mode][0] = 0;
       if (enc_mb.valid[mode])
       {
         for (cost=0, block=0; block<(mode==1?1:2); block++)
@@ -118,22 +121,22 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
           //--- get cost and reference frame for List 0 prediction ---
           bmcost[LIST_0] = INT_MAX;
-          list_prediction_cost(currMB, LIST_0, block, mode, enc_mb, bmcost, best_ref);
+          list_prediction_cost(currMB, LIST_0, block, mode, &enc_mb, bmcost, best_ref);
 
           if (bslice)
           {
             //--- get cost and reference frame for List 1 prediction ---
             bmcost[LIST_1] = INT_MAX;
-            list_prediction_cost(currMB, LIST_1, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, LIST_1, block, mode, &enc_mb, bmcost, best_ref);
 
             // Compute bipredictive cost between best list 0 and best list 1 references
-            list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, BI_PRED, block, mode, &enc_mb, bmcost, best_ref);
 
-            // Finally, if mode 16x16, compute cost for bipredictive ME vectore
-            if (params->BiPredMotionEstimation && mode == 1)
+            // currently Bi prediction ME is only supported for modes 1, 2, 3 and ref 0
+            if (is_bipred_enabled(mode))
             {
-              list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
-              list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L0, block, mode, &enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L1, block, mode, &enc_mb, bmcost, 0);
             }
             else
             {
@@ -142,7 +145,7 @@ void encode_one_macroblock_high (Macroblock *currMB)
             }
 
             // Determine prediction list based on mode cost
-            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bi_pred_me);
+            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bipred_me);
           }
           else // if (bslice)
           {
@@ -150,31 +153,14 @@ void encode_one_macroblock_high (Macroblock *currMB)
             cost      += bmcost[LIST_0];
           }
 
-          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice);
 
+          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice, bipred_me);
           //----- set reference frame and direction parameters -----
-          if (mode==3)
-          {
-            best8x8l0ref [3][block  ] = best8x8l0ref [3][  block+2] = best_ref[LIST_0];
-            best8x8pdir  [3][block  ] = best8x8pdir  [3][  block+2] = best_pdir;
-            best8x8l1ref [3][block  ] = best8x8l1ref [3][  block+2] = best_ref[LIST_1];
-          }
-          else if (mode==2)
-          {
-            best8x8l0ref [2][2*block] = best8x8l0ref [2][2*block+1] = best_ref[LIST_0];
-            best8x8pdir  [2][2*block] = best8x8pdir  [2][2*block+1] = best_pdir;
-            best8x8l1ref [2][2*block] = best8x8l1ref [2][2*block+1] = best_ref[LIST_1];
-          }
-          else
-          {
-            memset(&best8x8l0ref [1][0], best_ref[LIST_0], 4 * sizeof(char));
-            memset(&best8x8l1ref [1][0], best_ref[LIST_1], 4 * sizeof(char));
-            best8x8pdir  [1][0] = best8x8pdir  [1][1] = best8x8pdir  [1][2] = best8x8pdir  [1][3] = best_pdir;
-          }
+          set_block8x8_info(b8x8info, mode, block, best_ref, best_pdir, bipred_me);
 
           //--- set reference frames and motion vectors ---
-          if (mode>1 && block==0)
-            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1]);
+          if (mode>1 && block == 0)
+            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me);
         } // for (block=0; block<(mode==1?1:2); block++)
 
         if (cost < min_cost)
@@ -193,8 +179,8 @@ void encode_one_macroblock_high (Macroblock *currMB)
     {
       giRDOpt_B8OnlyFlag = 1;
 
-      tr8x8.cost8x8 = INT_MAX;
-      tr4x4.cost8x8 = INT_MAX;
+      tr8x8.mb_p8x8_cost = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
       //===== store coding state of macroblock =====
       store_coding_state (currMB, cs_mb);
 
@@ -202,19 +188,16 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
       if (params->Transform8x8Mode)
       {
-        tr8x8.cost8x8 = 0;
+        tr8x8.mb_p8x8_cost = 0;
         //===========================================================
         // Check 8x8 partition with transform size 8x8
         //===========================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block = 0; block < 4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
+          submacroblock_mode_decision(&enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 1);
-          best8x8mode       [block] = tr8x8.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr8x8.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr8x8.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr8x8.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr8x8);
         }
 
         // following params could be added in RD_8x8DATA structure
@@ -230,20 +213,16 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
       if (params->Transform8x8Mode != 2)
       {
-        tr4x4.cost8x8 = 0;
+        tr4x4.mb_p8x8_cost = 0;
         //=================================================================
         // Check 8x8, 8x4, 4x8 and 4x4 partitions with transform size 4x4
         //=================================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
+          submacroblock_mode_decision(&enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 0);
-
-          best8x8mode       [block] = tr4x4.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr4x4.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr4x4.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr4x4.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr4x4);
         }
         //--- re-set coding state (as it was before 8x8 block coding) ---
         // reset_coding_state (currMB, cs_mb);
@@ -254,14 +233,14 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
       // This is not enabled yet since mpr has reverse order.
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       //check cost for P8x8 for non-rdopt mode
       giRDOpt_B8OnlyFlag = 0;
     }
     else // if (enc_mb.valid[P8x8])
     {
-      tr4x4.cost8x8 = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
     }
 
     // Find a motion vector for the Skip mode
@@ -275,9 +254,6 @@ void encode_one_macroblock_high (Macroblock *currMB)
 
   //========= C H O O S E   B E S T   M A C R O B L O C K   M O D E =========
   //-------------------------------------------------------------------------
-  if (params->BiPredMotionEstimation)
-    img->bi_pred_me[1] =0;  
-
   if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
   {
     // precompute all new chroma intra prediction modes
@@ -323,15 +299,9 @@ void encode_one_macroblock_high (Macroblock *currMB)
         i16mode = 0; 
       }
       //--- for INTER16x16 check all prediction directions ---
-      if (mode==1 && bslice)
+      if (mode == 1 && bslice)
       {
-        best8x8pdir[1][0] = best8x8pdir[1][1] = best8x8pdir[1][2] = best8x8pdir[1][3] = (char) ctr16x16;
-
-        if ( (bslice) && (params->BiPredMotionEstimation) 
-          && (ctr16x16 == 2 && img->bi_pred_me[mode] < 2 && mode == 1))
-          ctr16x16--;
-        if (ctr16x16 < 2) 
-          index--;
+        update_prediction_for_mode16x16(b8x8info, ctr16x16, &index);
         ctr16x16++;
       }
 
@@ -344,10 +314,10 @@ void encode_one_macroblock_high (Macroblock *currMB)
       }
       else
       {
-        
-      if (params->SkipIntraInInterSlices && !intra && mode >= I4MB && best_mode <=3 && currMB->cbp == 0)
-        continue;
-    }
+
+        if (params->SkipIntraInInterSlices && !intra && mode >= I4MB && best_mode <=3 && currMB->cbp == 0)
+          continue;
+      }
 
       // check if weights are in valid range for biprediction.
       if (bslice && active_pps->weighted_bipred_idc == 1 && mode < P8x8) 
@@ -357,13 +327,13 @@ void encode_one_macroblock_high (Macroblock *currMB)
         Boolean invalid_mode = FALSE;
         for (cur_blk = 0; cur_blk < 4; cur_blk ++)
         {
-          if (best8x8pdir[mode][cur_blk] == 2)
+          if (b8x8info->best8x8pdir[mode][cur_blk] == 2)
           { 
             for (cur_comp = 0; cur_comp < (active_sps->chroma_format_idc == YUV400 ? 1 : 3) ; cur_comp ++)
             {
-              weight_sum = 
-                wbp_weight[0][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp] + 
-                wbp_weight[1][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp];
+              best8x8l0ref = (int) b8x8info->best8x8l0ref[mode][cur_blk];
+              best8x8l1ref = (int) b8x8info->best8x8l1ref[mode][cur_blk];
+              weight_sum = wbp_weight[0][best8x8l0ref][best8x8l1ref][cur_comp] + wbp_weight[1][best8x8l0ref][best8x8l1ref][cur_comp];
 
               if (weight_sum < -128 ||  weight_sum > 127) 
               {
@@ -376,19 +346,11 @@ void encode_one_macroblock_high (Macroblock *currMB)
           }
         }
         if (invalid_mode == TRUE)
-        {       
-          if ((params->BiPredMotionEstimation) && ctr16x16 == 2 
-            && img->bi_pred_me[mode] < 2 && mode == 1) 
-            img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
           continue;
-        }
       }
       if (enc_mb.valid[mode])
-        compute_mode_RD_cost(mode, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
+        compute_mode_RD_cost(mode, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
 
-      if ((params->BiPredMotionEstimation) && (bslice) && ctr16x16 == 2 
-        && img->bi_pred_me[mode] < 2 && mode == 1 && best8x8pdir[1][0] == 2) 
-        img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
     }// for (ctr16x16=0, index=0; index<max_index; index++)
   }// for (currMB->c_ipred_mode=DC_PRED_8; currMB->c_ipred_mode<=max_chroma_pred_mode; currMB->c_ipred_mode++)                     
 
diff --git a/lencod/src/md_highfast.c b/lencod/src/md_highfast.c
index c02f314..7bcfe72 100644
--- a/lencod/src/md_highfast.c
+++ b/lencod/src/md_highfast.c
@@ -54,17 +54,19 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
   short       bslice      = (img->type==B_SLICE);
   short       pslice      = (img->type==P_SLICE) || (img->type==SP_SLICE);
   short       intra       = (islice || (pslice && img->mb_y==img->mb_y_upd && img->mb_y_upd!=img->mb_y_intra));
-
+  int         best8x8l0ref, best8x8l1ref; 
 
   int         prev_mb_nr  = FmoGetPreviousMBNr(img->current_mb_nr);
   Macroblock* prevMB      = (prev_mb_nr >= 0) ? &img->mb_data[prev_mb_nr]:NULL ;
+  Block8x8Info *b8x8info   = img->b8x8info;
 
   short   *allmvs = img->all_mv[0][0][0][0][0];
   short   min_chroma_pred_mode, max_chroma_pred_mode;
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
   // Fast Mode Decision
   short inter_skip = 0, intra_skip = 0;
+  short  bipred_me;
   int cost16 = 0, mode16 = 0;
   double min_rate = 0, RDCost16 = DBL_MAX;
 
@@ -102,7 +104,7 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
         best_mode = 0;
         currMB->c_ipred_mode=DC_PRED_8;
         min_rdcost = max_rdcost;
-        compute_mode_RD_cost(0, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
+        compute_mode_RD_cost(0, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
       }
     }
 
@@ -114,8 +116,8 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
     //===== MOTION ESTIMATION FOR 16x16, 16x8, 8x16 BLOCKS =====
     for (min_cost=INT_MAX, mode=1; mode<4; mode++)
     {
-      bi_pred_me = 0;
-      img->bi_pred_me[mode]=0;
+      bipred_me = 0;
+      b8x8info->bipred8x8me[mode][0] = 0;
       if (enc_mb.valid[mode] && !inter_skip)
       {
         for (cost=0, block=0; block<(mode==1?1:2); block++)
@@ -129,22 +131,22 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
 
           //--- get cost and reference frame for List 0 prediction ---
           bmcost[LIST_0] = INT_MAX;
-          list_prediction_cost(currMB, LIST_0, block, mode, enc_mb, bmcost, best_ref);
+          list_prediction_cost(currMB, LIST_0, block, mode, &enc_mb, bmcost, best_ref);
 
           if (bslice)
           {
             //--- get cost and reference frame for List 1 prediction ---
             bmcost[LIST_1] = INT_MAX;
-            list_prediction_cost(currMB, LIST_1, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, LIST_1, block, mode, &enc_mb, bmcost, best_ref);
 
             // Compute bipredictive cost between best list 0 and best list 1 references
-            list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, BI_PRED, block, mode, &enc_mb, bmcost, best_ref);
 
-            // Finally, if mode 16x16, compute cost for bipredictive ME vectore
-            if (params->BiPredMotionEstimation && mode == 1)
+            // currently Bi prediction ME is only supported for modes 1, 2, 3 and ref 0
+            if (is_bipred_enabled(mode))
             {
-              list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
-              list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L0, block, mode, &enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L1, block, mode, &enc_mb, bmcost, 0);
             }
             else
             {
@@ -153,7 +155,7 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
             }
 
             // Determine prediction list based on mode cost
-            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bi_pred_me);
+            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bipred_me);
           }
           else // if (bslice)
           {
@@ -161,31 +163,13 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
             cost      += bmcost[LIST_0];
           }
 
-          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice);
-
+          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice, bipred_me);
           //----- set reference frame and direction parameters -----
-          if (mode==3)
-          {
-            best8x8l0ref [3][block  ] = best8x8l0ref [3][  block+2] = best_ref[LIST_0];
-            best8x8pdir  [3][block  ] = best8x8pdir  [3][  block+2] = best_pdir;
-            best8x8l1ref [3][block  ] = best8x8l1ref [3][  block+2] = best_ref[LIST_1];
-          }
-          else if (mode==2)
-          {
-            best8x8l0ref [2][2*block] = best8x8l0ref [2][2*block+1] = best_ref[LIST_0];
-            best8x8pdir  [2][2*block] = best8x8pdir  [2][2*block+1] = best_pdir;
-            best8x8l1ref [2][2*block] = best8x8l1ref [2][2*block+1] = best_ref[LIST_1];
-          }
-          else
-          {
-            memset(&best8x8l0ref [1][0], best_ref[LIST_0], 4 * sizeof(char));
-            memset(&best8x8l1ref [1][0], best_ref[LIST_1], 4 * sizeof(char));
-            best8x8pdir  [1][0] = best8x8pdir  [1][1] = best8x8pdir  [1][2] = best8x8pdir  [1][3] = best_pdir;
-          }
-
+          set_block8x8_info(b8x8info, mode, block, best_ref, best_pdir, bipred_me);
+          
           //--- set reference frames and motion vectors ---
           if (mode>1 && block==0)
-            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1]);
+            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me);
         } // for (block=0; block<(mode==1?1:2); block++)
 
 
@@ -205,20 +189,12 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
             //--- for INTER16x16 check all prediction directions ---
             if (bslice)
             {
-              best8x8pdir[1][0] = best8x8pdir[1][1] = best8x8pdir[1][2] = best8x8pdir[1][3] = ctr16x16;
-
-              if ( (bslice) && (params->BiPredMotionEstimation)
-                && (ctr16x16 == 2 && img->bi_pred_me[mode] < 2 && mode == 1))
-                ctr16x16--;
+              update_prediction_for_mode16x16(b8x8info, ctr16x16, &index);
               ctr16x16++;
             }
-
+            
             currMB->c_ipred_mode=DC_PRED_8;
-            compute_mode_RD_cost(mode, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
-
-            if ((params->BiPredMotionEstimation) && (bslice) && ctr16x16 == 2
-              && img->bi_pred_me[mode] < 2 && mode == 1 && best8x8pdir[1][0] == 2)
-              img->bi_pred_me[mode] = img->bi_pred_me[mode] + 1;
+            compute_mode_RD_cost(mode, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
           } // for (ctr16x16=0, k=0; k<1; k++)
 
           if(pslice)
@@ -228,9 +204,9 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
             if(params->EarlySkipEnable)
             {
               //===== check for SKIP mode =====
-              if ( currMB->cbp==0 && enc_picture->ref_idx[LIST_0][img->block_y][img->block_x]==0 &&
-                enc_picture->mv[LIST_0][img->block_y][img->block_x][0]==allmvs[0] &&
-                enc_picture->mv[LIST_0][img->block_y][img->block_x][1]==allmvs[1]               )
+              if ( currMB->cbp==0 && enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x]==0 &&
+                enc_picture->motion.mv[LIST_0][img->block_y][img->block_x][0]==allmvs[0] &&
+                enc_picture->motion.mv[LIST_0][img->block_y][img->block_x][1]==allmvs[1]               )
               {
                 inter_skip = 1;
                 best_mode = 0;
@@ -261,8 +237,8 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
     {
       giRDOpt_B8OnlyFlag = 1;
 
-      tr8x8.cost8x8 = INT_MAX;
-      tr4x4.cost8x8 = INT_MAX;
+      tr8x8.mb_p8x8_cost = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
       //===== store coding state of macroblock =====
       store_coding_state (currMB, cs_mb);
 
@@ -270,19 +246,16 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
 
       if (params->Transform8x8Mode)
       {
-        tr8x8.cost8x8 = 0;
+        tr8x8.mb_p8x8_cost = 0;
         //===========================================================
         // Check 8x8 partition with transform size 8x8
         //===========================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
+          submacroblock_mode_decision(&enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 1);
-          best8x8mode       [block] = tr8x8.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr8x8.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr8x8.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr8x8.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr8x8);
         }
 
         // following params could be added in RD_8x8DATA structure
@@ -298,20 +271,16 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
 
       if (params->Transform8x8Mode != 2)
       {
-        tr4x4.cost8x8 = 0;
+        tr4x4.mb_p8x8_cost = 0;
         //=================================================================
         // Check 8x8, 8x4, 4x8 and 4x4 partitions with transform size 4x4
         //=================================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
+          submacroblock_mode_decision(&enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 0);
-
-          best8x8mode       [block] = tr4x4.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr4x4.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr4x4.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr4x4.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr4x4);
         }
         //--- re-set coding state (as it was before 8x8 block coding) ---
         // reset_coding_state (currMB, cs_mb);
@@ -322,14 +291,14 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
 
       // This is not enabled yet since mpr has reverse order.
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       //check cost for P8x8 for non-rdopt mode
       giRDOpt_B8OnlyFlag = 0;
     }
     else // if (enc_mb.valid[P8x8])
     {
-      tr4x4.cost8x8 = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
     }
 
   }
@@ -359,9 +328,6 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
       // if Fast High mode, compute  inter modes separate process for inter/intra
       max_index = ((!intra && params->SelectiveIntraEnable ) ? 5 : 9);
 
-      if (params->BiPredMotionEstimation)
-        img->bi_pred_me[1] =0;
-
       if (((img->yuv_format != YUV400) && !IS_INDEPENDENT(params)) && max_index != 5)
       {
         // precompute all new chroma intra prediction modes
@@ -410,13 +376,7 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
           //--- for INTER16x16 check all prediction directions ---
           if (mode==1 && bslice)
           {
-            best8x8pdir[1][0] = best8x8pdir[1][1] = best8x8pdir[1][2] = best8x8pdir[1][3] = (char) ctr16x16;
-
-            if ( (bslice) && (params->BiPredMotionEstimation)
-              && (ctr16x16 == 2 && img->bi_pred_me[mode] < 2 && mode == 1))
-              ctr16x16--;
-            if (ctr16x16 < 2)
-              index--;
+            update_prediction_for_mode16x16(b8x8info, ctr16x16, &index);
             ctr16x16++;
           }
 
@@ -432,14 +392,13 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
             Boolean invalid_mode = FALSE;
             for (cur_blk = 0; cur_blk < 4; cur_blk ++)
             {
-              if (best8x8pdir[mode][cur_blk] == 2)
+              if (b8x8info->best8x8pdir[mode][cur_blk] == 2)
               {
                 for (cur_comp = 0; cur_comp < (active_sps->chroma_format_idc == YUV400 ? 1 : 3) ; cur_comp ++)
                 {
-                  weight_sum =
-                    wbp_weight[0][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp] +
-                    wbp_weight[1][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp];
-
+                  best8x8l0ref = (int) b8x8info->best8x8l0ref[mode][cur_blk];
+                  best8x8l1ref = (int) b8x8info->best8x8l1ref[mode][cur_blk];
+                  weight_sum = wbp_weight[0][best8x8l0ref][best8x8l1ref][cur_comp] + wbp_weight[1][best8x8l0ref][best8x8l1ref][cur_comp];
                   if (weight_sum < -128 ||  weight_sum > 127)
                   {
                     invalid_mode = TRUE;
@@ -451,20 +410,11 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
               }
             }
             if (invalid_mode == TRUE)
-            {
-              if ((params->BiPredMotionEstimation) && ctr16x16 == 2
-                && img->bi_pred_me[mode] < 2 && mode == 1)
-                img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
-              continue;
-            }
+               continue;
           }
 
           if (enc_mb.valid[mode])
-            compute_mode_RD_cost(mode, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
-
-          if ((params->BiPredMotionEstimation) && (bslice) && ctr16x16 == 2
-            && img->bi_pred_me[mode] < 2 && mode == 1 && best8x8pdir[1][0] == 2)
-            img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
+            compute_mode_RD_cost(mode, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
         }// for (ctr16x16=0, index=0; index<max_index; index++)
       }// for (currMB->c_ipred_mode=DC_PRED_8; currMB->c_ipred_mode<=max_chroma_pred_mode; currMB->c_ipred_mode++)
 
@@ -531,7 +481,7 @@ void encode_one_macroblock_highfast (Macroblock *currMB)
               }
 
               if (enc_mb.valid[mode])
-                compute_mode_RD_cost(mode, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
+                compute_mode_RD_cost(mode, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
             } // for (index = 5; index < max_index; index++)
           }
         }
@@ -626,10 +576,10 @@ static void fast_mode_intra_decision(Macroblock *currMB, short *intra_skip, doub
 
     for(i = 0; i < 8; i++)
     {
-      SBE += iabs(imgUV_org[0][img->opix_c_y][img->opix_c_x+i] - enc_picture->imgUV[0][img->pix_c_y-1][img->pix_c_x+i]);
-      SBE += iabs(imgUV_org[0][img->opix_c_y+i][img->opix_c_x] - enc_picture->imgUV[0][img->pix_c_y+i][img->pix_c_x-1]);
-      SBE += iabs(imgUV_org[1][img->opix_c_y][img->opix_c_x+i] - enc_picture->imgUV[1][img->pix_c_y-1][img->pix_c_x+i]);
-      SBE += iabs(imgUV_org[1][img->opix_c_y+i][img->opix_c_x] - enc_picture->imgUV[1][img->pix_c_y+i][img->pix_c_x-1]);
+      SBE += iabs(pImgOrg[1][img->opix_c_y][img->opix_c_x+i] - enc_picture->imgUV[0][img->pix_c_y-1][img->pix_c_x+i]);
+      SBE += iabs(pImgOrg[1][img->opix_c_y+i][img->opix_c_x] - enc_picture->imgUV[0][img->pix_c_y+i][img->pix_c_x-1]);
+      SBE += iabs(pImgOrg[2][img->opix_c_y][img->opix_c_x+i] - enc_picture->imgUV[1][img->pix_c_y-1][img->pix_c_x+i]);
+      SBE += iabs(pImgOrg[2][img->opix_c_y+i][img->opix_c_x] - enc_picture->imgUV[1][img->pix_c_y+i][img->pix_c_x-1]);
     }
     ABE = 1.0/64 * SBE;
   }
diff --git a/lencod/src/md_highloss.c b/lencod/src/md_highloss.c
index 2eb09c7..9c00bf8 100644
--- a/lencod/src/md_highloss.c
+++ b/lencod/src/md_highloss.c
@@ -49,6 +49,7 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
   int         mb_available_up;
   int         mb_available_left;
   int         mb_available_up_left;
+  int         best8x8l0ref, best8x8l1ref; 
 
   short       islice      = (short) (img->type==I_SLICE);
   short       bslice      = (short) (img->type==B_SLICE);
@@ -59,12 +60,14 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
 
   int         prev_mb_nr  = FmoGetPreviousMBNr(img->current_mb_nr);
   Macroblock* prevMB      = (prev_mb_nr >= 0) ? &img->mb_data[prev_mb_nr]:NULL ;
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
+  Block8x8Info *b8x8info   = img->b8x8info;
 
   short   min_chroma_pred_mode, max_chroma_pred_mode;
 
-  short inter_skip = 0;
-  double min_rate = 0;
+  short   inter_skip = 0;
+  short   bipred_me = 0;
+  double  min_rate = 0;
 
   if(params->SearchMode == UM_HEX)
   {
@@ -110,8 +113,8 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
       //===== MOTION ESTIMATION FOR 16x16, 16x8, 8x16 BLOCKS =====
       for (min_cost=INT_MAX, mode=1; mode<4; mode++)
       {
-        bi_pred_me = 0;
-        img->bi_pred_me[mode]=0;
+        bipred_me = 0;
+        b8x8info->bipred8x8me[mode][0] = 0;
         if (enc_mb.valid[mode])
         {
           for (cost=0, block=0; block<(mode==1?1:2); block++)
@@ -125,22 +128,22 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
 
             //--- get cost and reference frame for List 0 prediction ---
             bmcost[LIST_0] = INT_MAX;
-            list_prediction_cost(currMB, LIST_0, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, LIST_0, block, mode, &enc_mb, bmcost, best_ref);
 
             if (bslice)
             {
               //--- get cost and reference frame for List 1 prediction ---
               bmcost[LIST_1] = INT_MAX;
-              list_prediction_cost(currMB, LIST_1, block, mode, enc_mb, bmcost, best_ref);
+              list_prediction_cost(currMB, LIST_1, block, mode, &enc_mb, bmcost, best_ref);
 
               // Compute bipredictive cost between best list 0 and best list 1 references
-              list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);
+              list_prediction_cost(currMB, BI_PRED, block, mode, &enc_mb, bmcost, best_ref);
 
-              // Finally, if mode 16x16, compute cost for bipredictive ME vectore
-              if (params->BiPredMotionEstimation && mode == 1)
+              // currently Bi prediction ME is only supported for modes 1, 2, 3
+              if (is_bipred_enabled(mode))
               {
-                list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
-                list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
+                list_prediction_cost(currMB, BI_PRED_L0, block, mode, &enc_mb, bmcost, 0);
+                list_prediction_cost(currMB, BI_PRED_L1, block, mode, &enc_mb, bmcost, 0);
               }
               else
               {
@@ -149,7 +152,7 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
               }
 
               // Determine prediction list based on mode cost
-              determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bi_pred_me);
+              determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bipred_me);
             }
             else // if (bslice)
             {
@@ -157,31 +160,14 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
               cost      += bmcost[LIST_0];
             }
 
-            assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice);
-
+            assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice, bipred_me);
             //----- set reference frame and direction parameters -----
-            if (mode==3)
-            {
-              best8x8l0ref [3][block  ] = best8x8l0ref [3][  block+2] = best_ref[LIST_0];
-              best8x8pdir  [3][block  ] = best8x8pdir  [3][  block+2] = best_pdir;
-              best8x8l1ref [3][block  ] = best8x8l1ref [3][  block+2] = best_ref[LIST_1];
-            }
-            else if (mode==2)
-            {
-              best8x8l0ref [2][2*block] = best8x8l0ref [2][2*block+1] = best_ref[LIST_0];
-              best8x8pdir  [2][2*block] = best8x8pdir  [2][2*block+1] = best_pdir;
-              best8x8l1ref [2][2*block] = best8x8l1ref [2][2*block+1] = best_ref[LIST_1];
-            }
-            else
-            {
-              memset(&best8x8l0ref [1][0], best_ref[LIST_0], 4 * sizeof(char));
-              memset(&best8x8l1ref [1][0], best_ref[LIST_1], 4 * sizeof(char));
-              best8x8pdir  [1][0] = best8x8pdir  [1][1] = best8x8pdir  [1][2] = best8x8pdir  [1][3] = best_pdir;
-            }
-
+            set_block8x8_info(b8x8info, mode, block, best_ref, best_pdir, bipred_me);
+            
+            
             //--- set reference frames and motion vectors ---
             if (mode>1 && block==0)
-              SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1]);
+              SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me);
           } // for (block=0; block<(mode==1?1:2); block++)
 
           if (cost < min_cost)
@@ -200,8 +186,8 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
       {
         giRDOpt_B8OnlyFlag = 1;
 
-        tr8x8.cost8x8 = INT_MAX;
-        tr4x4.cost8x8 = INT_MAX;
+        tr8x8.mb_p8x8_cost = INT_MAX;
+        tr4x4.mb_p8x8_cost = INT_MAX;
         //===== store coding state of macroblock =====
         store_coding_state (currMB, cs_mb);
 
@@ -209,19 +195,16 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
 
         if (params->Transform8x8Mode)
         {
-          tr8x8.cost8x8 = 0;
+          tr8x8.mb_p8x8_cost = 0;
           //===========================================================
           // Check 8x8 partition with transform size 8x8
           //===========================================================
           //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
           for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
           {
-            submacroblock_mode_decision(enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
+            submacroblock_mode_decision(&enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
               &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 1);
-            best8x8mode       [block] = tr8x8.part8x8mode [block];
-            best8x8pdir [P8x8][block] = tr8x8.part8x8pdir [block];
-            best8x8l0ref[P8x8][block] = tr8x8.part8x8l0ref[block];
-            best8x8l1ref[P8x8][block] = tr8x8.part8x8l1ref[block];
+            set_subblock8x8_info(b8x8info, P8x8, block, &tr8x8);
           }
 
           // following params could be added in RD_8x8DATA structure
@@ -237,20 +220,16 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
 
         if (params->Transform8x8Mode != 2)
         {
-          tr4x4.cost8x8 = 0;
+          tr4x4.mb_p8x8_cost = 0;
           //=================================================================
           // Check 8x8, 8x4, 4x8 and 4x4 partitions with transform size 4x4
           //=================================================================
           //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
           for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
           {
-            submacroblock_mode_decision(enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
+            submacroblock_mode_decision(&enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
               &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 0);
-
-            best8x8mode       [block] = tr4x4.part8x8mode [block];
-            best8x8pdir [P8x8][block] = tr4x4.part8x8pdir [block];
-            best8x8l0ref[P8x8][block] = tr4x4.part8x8l0ref[block];
-            best8x8l1ref[P8x8][block] = tr4x4.part8x8l1ref[block];
+            set_subblock8x8_info(b8x8info, P8x8, block, &tr4x4);
           }
           //--- re-set coding state (as it was before 8x8 block coding) ---
           // reset_coding_state (currMB, cs_mb);
@@ -261,14 +240,14 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
 
         // This is not enabled yet since mpr has reverse order.
         if (params->RCEnable)
-          rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+          rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
         //check cost for P8x8 for non-rdopt mode
         giRDOpt_B8OnlyFlag = 0;
       }
       else // if (enc_mb.valid[P8x8])
       {
-        tr4x4.cost8x8 = INT_MAX;
+        tr4x4.mb_p8x8_cost = INT_MAX;
       }
 
       // Find a motion vector for the Skip mode
@@ -284,9 +263,6 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
     //-------------------------------------------------------------------------
 
    {
-     if (params->BiPredMotionEstimation)
-       img->bi_pred_me[1] =0;
-
      if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
      {
        // precompute all new chroma intra prediction modes
@@ -295,8 +271,8 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
        if (params->FastCrIntraDecision )
        {
          IntraChromaRDDecision(currMB, enc_mb);
-      min_chroma_pred_mode = (short) currMB->c_ipred_mode;
-      max_chroma_pred_mode = (short) currMB->c_ipred_mode;
+         min_chroma_pred_mode = (short) currMB->c_ipred_mode;
+         max_chroma_pred_mode = (short) currMB->c_ipred_mode;
        }
        else
        {
@@ -332,13 +308,7 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
          //--- for INTER16x16 check all prediction directions ---
          if (mode==1 && bslice)
          {
-           best8x8pdir[1][0] = best8x8pdir[1][1] = best8x8pdir[1][2] = best8x8pdir[1][3] = (char) ctr16x16;
-
-           if ( (bslice) && (params->BiPredMotionEstimation)
-             && (ctr16x16 == 2 && img->bi_pred_me[mode] < 2 && mode == 1))
-             ctr16x16--;
-           if (ctr16x16 < 2)
-             index--;
+           update_prediction_for_mode16x16(b8x8info, ctr16x16, &index);
            ctr16x16++;
          }
 
@@ -354,13 +324,13 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
            Boolean invalid_mode = FALSE;
            for (cur_blk = 0; cur_blk < 4; cur_blk ++)
            {
-             if (best8x8pdir[mode][cur_blk] == 2)
+             if (b8x8info->best8x8pdir[mode][cur_blk] == 2)
              {
                for (cur_comp = 0; cur_comp < (active_sps->chroma_format_idc == YUV400 ? 1 : 3) ; cur_comp ++)
                {
-                 weight_sum =
-                   wbp_weight[0][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp] +
-                   wbp_weight[1][(int) best8x8l0ref[mode][cur_blk]][(int) best8x8l1ref[mode][cur_blk]][cur_comp];
+                 best8x8l0ref = (int) b8x8info->best8x8l0ref[mode][cur_blk];
+                 best8x8l1ref = (int) b8x8info->best8x8l1ref[mode][cur_blk];
+                 weight_sum = wbp_weight[0][best8x8l0ref][best8x8l1ref][cur_comp] + wbp_weight[1][best8x8l0ref][best8x8l1ref][cur_comp];
 
                  if (weight_sum < -128 ||  weight_sum > 127)
                  {
@@ -373,20 +343,12 @@ void encode_one_macroblock_highloss (Macroblock *currMB)
              }
            }
            if (invalid_mode == TRUE)
-           {
-             if ((params->BiPredMotionEstimation) && ctr16x16 == 2
-               && img->bi_pred_me[mode] < 2 && mode == 1)
-            img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
              continue;
-           }
          }
 
          if (enc_mb.valid[mode])
-           compute_mode_RD_cost(mode, currMB, enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
+           compute_mode_RD_cost(mode, currMB, &enc_mb, &min_rdcost, &min_dcost, &min_rate, i16mode, bslice, &inter_skip);
 
-         if ((params->BiPredMotionEstimation) && (bslice) && ctr16x16 == 2
-           && img->bi_pred_me[mode] < 2 && mode == 1 && best8x8pdir[1][0] == 2)
-        img->bi_pred_me[mode] = (short) (img->bi_pred_me[mode] + 1); 
        }// for (ctr16x16=0, index=0; index<max_index; index++)
      }// for (currMB->c_ipred_mode=DC_PRED_8; currMB->c_ipred_mode<=max_chroma_pred_mode; currMB->c_ipred_mode++)
 
diff --git a/lencod/src/md_low.c b/lencod/src/md_low.c
index 60944d9..63fda5c 100644
--- a/lencod/src/md_low.c
+++ b/lencod/src/md_low.c
@@ -25,6 +25,7 @@
 #include "me_umhex.h"
 #include "me_umhexsmp.h"
 #include "macroblock.h"
+#include "q_around.h"
 
 
 //==== MODULE PARAMETERS ====
@@ -33,7 +34,6 @@ static imgpel temp_imgU[16][16];
 static imgpel temp_imgV[16][16];
 
 
-
 /*!
 *************************************************************************************
 * \brief
@@ -43,7 +43,7 @@ static imgpel temp_imgV[16][16];
 void encode_one_macroblock_low (Macroblock *currMB)
 {
 
-  int         block, mode, i, j, k, dummy;
+  int         block, mode, i=0, j, k, dummy;
   char        best_pdir;
   RD_PARAMS   enc_mb;
   char        best_ref[2] = {0, -1};
@@ -60,18 +60,18 @@ void encode_one_macroblock_low (Macroblock *currMB)
   short       pslice      = (short) ((img->type==P_SLICE) || (img->type==SP_SLICE));
   short       intra       = (short) (islice || (pslice && img->mb_y==img->mb_y_upd && img->mb_y_upd!=img->mb_y_intra));
   int         lambda_mf[3];
-  int         pix_x, pix_y;
   int         prev_mb_nr  = FmoGetPreviousMBNr(img->current_mb_nr);
   Macroblock* prevMB      = (prev_mb_nr >= 0) ? &img->mb_data[prev_mb_nr]:NULL ;
+  Block8x8Info *b8x8info   = img->b8x8info;
 
   char   **ipredmodes = img->ipredmode;
   short   *allmvs = params->IntraProfile ? NULL: img->all_mv[0][0][0][0][0];
   int     ****i4p;  //for non-RD-opt. mode
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
   int tmp_8x8_flag, tmp_no_mbpart;
   // Fast Mode Decision
-  short inter_skip = 0;
+  short bipred_me, inter_skip = 0;
 
 
   if(params->SearchMode == UM_HEX)
@@ -88,7 +88,6 @@ void encode_one_macroblock_low (Macroblock *currMB)
   //===== Setup Macroblock encoding parameters =====
   init_enc_mb_params(currMB, &enc_mb, intra, bslice);
 
-
   // reset chroma intra predictor to default
   currMB->c_ipred_mode = DC_PRED_8;
 
@@ -113,8 +112,8 @@ void encode_one_macroblock_low (Macroblock *currMB)
     //===== MOTION ESTIMATION FOR 16x16, 16x8, 8x16 BLOCKS =====
     for (min_cost=INT_MAX, mode=1; mode<4; mode++)
     {
-      bi_pred_me = 0;
-      img->bi_pred_me[mode]=0;
+      bipred_me = 0;
+      b8x8info->bipred8x8me[mode][0] = 0;
       if (enc_mb.valid[mode] && !inter_skip)
       {
         for (cost=0, block=0; block<(mode==1?1:2); block++)
@@ -128,22 +127,22 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
           //--- get cost and reference frame for List 0 prediction ---
           bmcost[LIST_0] = INT_MAX;
-          list_prediction_cost(currMB, LIST_0, block, mode, enc_mb, bmcost, best_ref);
+          list_prediction_cost(currMB, LIST_0, block, mode, &enc_mb, bmcost, best_ref);
 
           if (bslice)
           {
             //--- get cost and reference frame for List 1 prediction ---
             bmcost[LIST_1] = INT_MAX;
-            list_prediction_cost(currMB, LIST_1, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, LIST_1, block, mode, &enc_mb, bmcost, best_ref);
 
             // Compute bipredictive cost between best list 0 and best list 1 references
-            list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);
+            list_prediction_cost(currMB, BI_PRED, block, mode, &enc_mb, bmcost, best_ref);
 
-            // Finally, if mode 16x16, compute cost for bipredictive ME vectore
-            if (params->BiPredMotionEstimation && mode == 1)
+            // currently Bi prediction ME is only supported for modes 1, 2, 3
+            if (is_bipred_enabled(mode))
             {
-              list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
-              list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L0, block, mode, &enc_mb, bmcost, 0);
+              list_prediction_cost(currMB, BI_PRED_L1, block, mode, &enc_mb, bmcost, 0);
             }
             else
             {
@@ -152,7 +151,7 @@ void encode_one_macroblock_low (Macroblock *currMB)
             }
 
             // Determine prediction list based on mode cost
-            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bi_pred_me);
+            determine_prediction_list(mode, bmcost, best_ref, &best_pdir, &cost, &bipred_me);
           }
           else // if (bslice)
           {
@@ -160,31 +159,13 @@ void encode_one_macroblock_low (Macroblock *currMB)
             cost      += bmcost[LIST_0];
           }
 
-          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice);
-
+          assign_enc_picture_params(mode, best_pdir, block, enc_mb.list_offset[LIST_0], best_ref[LIST_0], best_ref[LIST_1], bslice, bipred_me);          
           //----- set reference frame and direction parameters -----
-          if (mode==3)
-          {
-            best8x8l0ref [3][block  ] = best8x8l0ref [3][  block+2] = best_ref[LIST_0];
-            best8x8pdir  [3][block  ] = best8x8pdir  [3][  block+2] = best_pdir;
-            best8x8l1ref [3][block  ] = best8x8l1ref [3][  block+2] = best_ref[LIST_1];
-          }
-          else if (mode==2)
-          {
-            best8x8l0ref [2][2*block] = best8x8l0ref [2][2*block+1] = best_ref[LIST_0];
-            best8x8pdir  [2][2*block] = best8x8pdir  [2][2*block+1] = best_pdir;
-            best8x8l1ref [2][2*block] = best8x8l1ref [2][2*block+1] = best_ref[LIST_1];
-          }
-          else
-          {
-            memset(&best8x8l0ref [1][0], best_ref[LIST_0], 4 * sizeof(char));
-            memset(&best8x8l1ref [1][0], best_ref[LIST_1], 4 * sizeof(char));
-            best8x8pdir  [1][0] = best8x8pdir  [1][1] = best8x8pdir  [1][2] = best8x8pdir  [1][3] = best_pdir;
-          }
+          set_block8x8_info(b8x8info, mode, block, best_ref, best_pdir, bipred_me);
 
           //--- set reference frames and motion vectors ---
           if (mode>1 && block==0)
-            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1]);
+            SetRefAndMotionVectors (currMB, block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me);
         } // for (block=0; block<(mode==1?1:2); block++)
 
         currMB->luma_transform_size_8x8_flag = 0;
@@ -212,8 +193,8 @@ void encode_one_macroblock_low (Macroblock *currMB)
     {
       giRDOpt_B8OnlyFlag = 1;
 
-      tr8x8.cost8x8 = INT_MAX;
-      tr4x4.cost8x8 = INT_MAX;
+      tr8x8.mb_p8x8_cost = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
       //===== store coding state of macroblock =====
       store_coding_state (currMB, cs_mb);
 
@@ -221,19 +202,16 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       if (params->Transform8x8Mode)
       {
-        tr8x8.cost8x8 = 0;
+        tr8x8.mb_p8x8_cost = 0;
         //===========================================================
         // Check 8x8 partition with transform size 8x8
         //===========================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block = 0; block < 4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
+          submacroblock_mode_decision(&enc_mb, &tr8x8, currMB, cofAC8x8ts[0][block], cofAC8x8ts[1][block], cofAC8x8ts[2][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 1);
-          best8x8mode       [block] = tr8x8.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr8x8.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr8x8.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr8x8.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr8x8);
         }
 
         // following params could be added in RD_8x8DATA structure
@@ -249,20 +227,16 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       if (params->Transform8x8Mode != 2)
       {
-        tr4x4.cost8x8 = 0;
+        tr4x4.mb_p8x8_cost = 0;
         //=================================================================
         // Check 8x8, 8x4, 4x8 and 4x4 partitions with transform size 4x4
         //=================================================================
         //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
         for (cost_direct=cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
         {
-          submacroblock_mode_decision(enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
+          submacroblock_mode_decision(&enc_mb, &tr4x4, currMB, cofAC8x8[block], cofAC8x8CbCr[0][block], cofAC8x8CbCr[1][block],
             &have_direct, bslice, block, &cost_direct, &cost, &cost8x8_direct, 0);
-
-          best8x8mode       [block] = tr4x4.part8x8mode [block];
-          best8x8pdir [P8x8][block] = tr4x4.part8x8pdir [block];
-          best8x8l0ref[P8x8][block] = tr4x4.part8x8l0ref[block];
-          best8x8l1ref[P8x8][block] = tr4x4.part8x8l1ref[block];
+          set_subblock8x8_info(b8x8info, P8x8, block, &tr4x4);
         }
         //--- re-set coding state (as it was before 8x8 block coding) ---
         // reset_coding_state (currMB, cs_mb);
@@ -274,54 +248,58 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       // This is not enabled yet since mpr has reverse order.
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       //check cost for P8x8 for non-rdopt mode
-      if (tr4x4.cost8x8 < min_cost || tr8x8.cost8x8 < min_cost)
+      if (tr4x4.mb_p8x8_cost < min_cost || tr8x8.mb_p8x8_cost < min_cost)
       {
         best_mode = P8x8;
+
+        if (img->AdaptiveRounding)
+          store_adaptive_rounding_parameters_luma (currMB, best_mode);		
+
         if (params->Transform8x8Mode == 2)
         {
-          min_cost = tr8x8.cost8x8;
+          min_cost = tr8x8.mb_p8x8_cost;
           currMB->luma_transform_size_8x8_flag=1;
         }
         else if (params->Transform8x8Mode)
         {
-          if (tr8x8.cost8x8 < tr4x4.cost8x8)
+          if (tr8x8.mb_p8x8_cost < tr4x4.mb_p8x8_cost)
           {
-            min_cost = tr8x8.cost8x8;
+            min_cost = tr8x8.mb_p8x8_cost;
             currMB->luma_transform_size_8x8_flag=1;
           }
-          else if(tr4x4.cost8x8 < tr8x8.cost8x8)
+          else if(tr4x4.mb_p8x8_cost < tr8x8.mb_p8x8_cost)
           {
-            min_cost = tr4x4.cost8x8;
+            min_cost = tr4x4.mb_p8x8_cost;
             currMB->luma_transform_size_8x8_flag=0;
           }
           else
           {
             if (GetBestTransformP8x8() == 0)
             {
-              min_cost = tr4x4.cost8x8;
+              min_cost = tr4x4.mb_p8x8_cost;
               currMB->luma_transform_size_8x8_flag=0;
             }
             else
             {
-              min_cost = tr8x8.cost8x8;
+              min_cost = tr8x8.mb_p8x8_cost;
               currMB->luma_transform_size_8x8_flag=1;
             }
           }
         }
         else
         {
-          min_cost = tr4x4.cost8x8;
+          min_cost = tr4x4.mb_p8x8_cost;
           currMB->luma_transform_size_8x8_flag=0;
         }
-      }// if ((tr4x4.cost8x8 < min_cost || tr8x8.cost8x8 < min_cost))
+      }// if ((tr4x4.mb_p8x8_cost < min_cost || tr8x8.mb_p8x8_cost < min_cost))
       giRDOpt_B8OnlyFlag = 0;
     }
     else // if (enc_mb.valid[P8x8])
     {
-      tr4x4.cost8x8 = INT_MAX;
+      tr4x4.mb_p8x8_cost = INT_MAX;
     }
 
     // Find a motion vector for the Skip mode
@@ -387,7 +365,7 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       //Rate control
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       min_cost  = cost;
       best_mode = 0;
@@ -409,6 +387,7 @@ void encode_one_macroblock_low (Macroblock *currMB)
     currMB->mb_type = I8MB;
     temp_cpb = Mode_Decision_for_new_Intra8x8Macroblock (currMB, enc_mb.lambda_md, &rd_cost);
 
+
     if (rd_cost <= min_rd_cost) //HYU_NOTE. bug fix. 08/15/07
     {
       currMB->cbp = temp_cpb;
@@ -429,31 +408,21 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       for(j=0; j<MB_BLOCK_SIZE; j++)
       {
-        pix_y = img->pix_y + j;
-        for(i=0; i<MB_BLOCK_SIZE; i++)
-        {
-          pix_x = img->pix_x + i;
-          temp_imgY[j][i] = enc_picture->imgY[pix_y][pix_x];
-        }
+        memcpy(temp_imgY[j], &enc_picture->imgY[img->pix_y + j][img->pix_x], MB_BLOCK_SIZE * sizeof (imgpel));
       }
 
       if (img->P444_joined)
       {
         for(j=0; j<MB_BLOCK_SIZE; j++)
         {
-          pix_y = img->pix_y + j;
-          for(i=0; i<MB_BLOCK_SIZE; i++)
-          {
-            pix_x = img->pix_x + i;
-            temp_imgU[j][i] = enc_picture->imgUV[0][pix_y][pix_x]; 
-            temp_imgV[j][i] = enc_picture->imgUV[1][pix_y][pix_x];
-          }
+          memcpy(temp_imgU[j], &enc_picture->imgUV[0][img->pix_y + j][img->pix_x], MB_BLOCK_SIZE * sizeof (imgpel));
+          memcpy(temp_imgV[j], &enc_picture->imgUV[1][img->pix_y + j][img->pix_x], MB_BLOCK_SIZE * sizeof (imgpel));
         }
       }
-      
+
       //Rate control
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       min_rd_cost  = rd_cost; 
       best_mode = I8MB;
@@ -486,11 +455,14 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
       //Rate control
       if (params->RCEnable)
-        rc_store_diff(img->opix_x, img->opix_y, curr_mpr);
+        rc_store_diff(img->opix_x, img->opix_y, mb_pred);
 
       min_rd_cost  = rd_cost; 
       best_mode = I4MB;
       tmp_8x8_flag = currMB->luma_transform_size_8x8_flag;
+
+      if (img->AdaptiveRounding)
+        store_adaptive_rounding_parameters_luma (currMB, best_mode);
     }
     else
     {
@@ -539,6 +511,10 @@ void encode_one_macroblock_low (Macroblock *currMB)
       best_mode   = I16MB;      
       min_rd_cost  = rd_cost; 
       currMB->cbp = pDCT_16x16 (currMB, PLANE_Y, i16mode);
+
+      if (img->AdaptiveRounding)
+        store_adaptive_rounding_parameters_luma (currMB, best_mode);
+
       if (img->P444_joined)
       {
         select_plane(PLANE_U);
@@ -616,6 +592,9 @@ void encode_one_macroblock_low (Macroblock *currMB)
             currMB->luma_transform_size_8x8_flag = best_transform_flag;
           LumaResidualCoding (currMB);
 
+          if (img->AdaptiveRounding)
+            store_adaptive_rounding_parameters_luma (currMB, best_mode);
+
           if (img->P444_joined)
           {
             if((currMB->cbp==0 && cmp_cbp[1] == 0 && cmp_cbp[2] == 0) &&(best_mode==0))
@@ -626,7 +605,7 @@ void encode_one_macroblock_low (Macroblock *currMB)
 
           //Rate control
           if (params->RCEnable)
-            rc_store_diff(img->opix_x,img->opix_y,curr_mpr);
+            rc_store_diff(img->opix_x,img->opix_y,mb_pred);
         }
       }
     }
@@ -644,6 +623,9 @@ void encode_one_macroblock_low (Macroblock *currMB)
     if ((img->yuv_format != YUV400) && (img->yuv_format != YUV444))
       ChromaResidualCoding (currMB);
 
+    if (img->AdaptiveRounding)
+      store_adaptive_rounding_parameters_chroma (currMB, best_mode);
+
     if (best_mode==I16MB)
     {
       img->i16offset = I16Offset  (currMB->cbp, i16mode);
@@ -655,18 +637,18 @@ void encode_one_macroblock_low (Macroblock *currMB)
     if(img->P444_joined)
     {
       if ((pslice) && best_mode==1 && currMB->cbp==0 && cmp_cbp[1] == 0 && cmp_cbp[2] == 0 &&
-        enc_picture->ref_idx[LIST_0][img->block_y][img->block_x]    == 0 &&
-        enc_picture->mv     [LIST_0][img->block_y][img->block_x][0] == allmvs[0] &&
-        enc_picture->mv     [LIST_0][img->block_y][img->block_x][1] == allmvs[1])
+        enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x]    == 0 &&
+        enc_picture->motion.mv     [LIST_0][img->block_y][img->block_x][0] == allmvs[0] &&
+        enc_picture->motion.mv     [LIST_0][img->block_y][img->block_x][1] == allmvs[1])
       {
         currMB->mb_type = currMB->b8mode[0] = currMB->b8mode[1] = currMB->b8mode[2] = currMB->b8mode[3] = 0;
         currMB->luma_transform_size_8x8_flag = 0;
       }
     }
     else if ((pslice) && best_mode==1 && currMB->cbp==0 &&
-      enc_picture->ref_idx[LIST_0][img->block_y][img->block_x]    == 0 &&
-      enc_picture->mv     [LIST_0][img->block_y][img->block_x][0] == allmvs[0] &&
-      enc_picture->mv     [LIST_0][img->block_y][img->block_x][1] == allmvs[1])
+      enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x]    == 0 &&
+      enc_picture->motion.mv     [LIST_0][img->block_y][img->block_x][0] == allmvs[0] &&
+      enc_picture->motion.mv     [LIST_0][img->block_y][img->block_x][1] == allmvs[1])
     {
       currMB->mb_type = currMB->b8mode[0] = currMB->b8mode[1] = currMB->b8mode[2] = currMB->b8mode[3] = 0;
       currMB->luma_transform_size_8x8_flag = 0;
@@ -711,5 +693,11 @@ void encode_one_macroblock_low (Macroblock *currMB)
   {
     img->intra_block[img->current_mb_nr] = IS_INTRA(currMB);
   }
+
+  /*update adaptive rounding offset params*/
+  if (img->AdaptiveRounding)
+  {
+    update_offset_params(currMB, best_mode, currMB->luma_transform_size_8x8_flag);
+  }
 }
 
diff --git a/lencod/src/me_epzs.c b/lencod/src/me_epzs.c
index 541a0f3..87dd65b 100644
--- a/lencod/src/me_epzs.c
+++ b/lencod/src/me_epzs.c
@@ -76,10 +76,10 @@ static int pattern_data[5][12][4] =
 };
 
 // Other definitions
-static const  char c_EPZSPattern[6][20]    = { "Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
-static const  char c_EPZSDualPattern[7][20] = { "Disabled","Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
-static const  char c_EPZSFixed[3][20] = { "Disabled","All P", "All P + B"};
-static const  char c_EPZSOther[2][20] = { "Disabled","Enabled"};
+static const char c_EPZSPattern[6][20]     = { "Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
+static const char c_EPZSDualPattern[7][20] = { "Disabled","Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
+static const char c_EPZSFixed[3][20]       = { "Disabled","All P", "All P + B"};
+static const char c_EPZSOther[2][20]       = { "Disabled","Enabled"};
 
 static int medthres[8];
 static int maxthres[8];
@@ -89,9 +89,12 @@ static int mv_scale[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES];
 
 static short **EPZSMap;  //!< Memory Map definition
 int ***EPZSDistortion;  //!< Array for storing SAD Values
+int ***EPZSBiDistortion;  //!< Array for storing SAD Values
 #if EPZSREF
+MotionVector *****EPZS_Motion;  //!< Array for storing Motion Vectors
 short ******EPZSMotion;  //!< Array for storing Motion Vectors
 #else
+MotionVector ****EPZS_Motion;  //!< Array for storing Motion Vectors
 short *****EPZSMotion;  //!< Array for storing Motion Vectors
 #endif
 
@@ -101,6 +104,28 @@ EPZSStructure *window_predictor, *window_predictor_extended;
 EPZSStructure *sdiamond,*square,*ediamond,*ldiamond, *sbdiamond, *pmvfast;
 EPZSColocParams *EPZSCo_located;
 
+/*!
+*************************************************************************************
+* \brief
+*    Determine stop criterion for EPZS
+*************************************************************************************
+*/
+static int EPZSDetermineStopCriterion(int* prevSad, PixelPos *block_a, PixelPos *block_b, PixelPos *block_c, int pic_pix_x2, int blocktype, int blocksize_x)
+{
+  int sadA, sadB, sadC, stopCriterion;
+
+  sadA = block_a->available ? prevSad[pic_pix_x2 - blocksize_x] : INT_MAX;
+  sadB = block_b->available ? prevSad[pic_pix_x2] : INT_MAX;
+  sadC = block_c->available ? prevSad[pic_pix_x2 + blocksize_x] : INT_MAX;
+
+  stopCriterion = imin(sadA,imin(sadB,sadC));
+  stopCriterion = imax(stopCriterion,minthres[blocktype]);
+  stopCriterion = imin(stopCriterion,maxthres[blocktype]);
+
+  stopCriterion = (9 * imax (medthres[blocktype], stopCriterion) + 2 * medthres[blocktype]) >> 3;
+  return stopCriterion;
+}
+
 // Functions
 /*!
 ************************************************************************
@@ -128,12 +153,12 @@ static EPZSColocParams* allocEPZScolocated(int size_x, int size_y, int mb_adapti
 
   s->size_x = size_x;
   s->size_y = size_y;
-  get_mem4Dshort (&(s->mv), 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE, 2);
+  get_mem3Dmv(&(s->frame), 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
 
   if (mb_adaptive_frame_field_flag)
   {
-    get_mem4Dshort (&(s->top_mv),   2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE, 2);
-    get_mem4Dshort (&(s->bottom_mv),2, size_y / BLOCK_SIZE/2, size_x / BLOCK_SIZE, 2);
+    get_mem3Dmv(&(s->top), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
+    get_mem3Dmv(&(s->bot), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
   }
 
   s->mb_adaptive_frame_field_flag  = mb_adaptive_frame_field_flag;
@@ -155,12 +180,12 @@ static void freeEPZScolocated(EPZSColocParams* p)
 {
   if (p)
   {
-    free_mem4Dshort (p->mv);
+    free_mem3Dmv (p->frame);
 
     if (p->mb_adaptive_frame_field_flag)
     {
-      free_mem4Dshort (p->top_mv);
-      free_mem4Dshort (p->bottom_mv);
+      free_mem3Dmv (p->top);
+      free_mem3Dmv (p->bot);
     }
 
     free(p);
@@ -250,6 +275,20 @@ static int RoundLog2 (int iValue)
   return iRet;
 }
 
+/*!
+***********************************************************************
+* \brief
+*    Add Predictor function
+*    
+***********************************************************************
+*/
+static inline int add_predictor(MotionVector *cur_mv, MotionVector prd_mv, int mvScale, int shift_mv)
+{
+  *cur_mv = prd_mv;
+  cur_mv->mv_x = rshift_rnd_sf((mvScale * cur_mv->mv_x), shift_mv);
+  cur_mv->mv_y = rshift_rnd_sf((mvScale * cur_mv->mv_y), shift_mv);
+  return (*((int*) cur_mv) != 0);
+}
 
 /*!
 ************************************************************************
@@ -328,7 +367,7 @@ static void EPZSWindowPredictorInit (short search_range, EPZSStructure * predict
 *    EPZS Global Initialization
 ************************************************************************
 */
-int EPZSInit (void)
+int EPZSInit (InputParameters *params, ImageParameters *img)
 {
   int pel_error_me = 1 << (img->bitdepth_luma - 8);
   int pel_error_me_cr = 1 << (img->bitdepth_chroma - 8);
@@ -392,13 +431,16 @@ int EPZSInit (void)
 
   //memory_size += get_offset_mem2Dshort(&EPZSMap, searcharray, searcharray, (searcharray>>1), (searcharray>>1));
   memory_size += get_mem3Dint (&EPZSDistortion, 6, 7, img->width/BLOCK_SIZE);
+  memory_size += get_mem3Dint (&EPZSBiDistortion, 6, 7, img->width/BLOCK_SIZE);
   memory_size += get_mem2Dshort (&EPZSMap, searcharray, searcharray );
 
   if (params->EPZSSpatialMem)
   {
 #if EPZSREF
+    memory_size += get_mem5Dmv (&EPZS_Motion, 6, img->max_num_references, 7, 4, img->width/BLOCK_SIZE);
     memory_size += get_mem6Dshort (&EPZSMotion, 6, img->max_num_references, 7, 4, img->width/BLOCK_SIZE, 2);
 #else
+    memory_size += get_mem4Dmv (&EPZS_Motion, 6, 7, 4, img->width/BLOCK_SIZE);
     memory_size += get_mem5Dshort (&EPZSMotion, 6, 7, 4, img->width/BLOCK_SIZE, 2);
 #endif
   }
@@ -461,7 +503,7 @@ int EPZSInit (void)
 *    Delete EPZS Alocated memory
 ************************************************************************
 */
-void EPZSDelete (void)
+void EPZSDelete (InputParameters *params)
 {
   if (params->EPZSTemporal)
     freeEPZScolocated (EPZSCo_located);
@@ -469,6 +511,7 @@ void EPZSDelete (void)
   //free_offset_mem2Dshort(EPZSMap, searcharray, (searcharray>>1), (searcharray>>1));
   free_mem2Dshort(EPZSMap);
   free_mem3Dint  (EPZSDistortion);
+  free_mem3Dint  (EPZSBiDistortion);
   freeEPZSpattern(window_predictor_extended);
   freeEPZSpattern(window_predictor);
   freeEPZSpattern(predictor);
@@ -482,8 +525,10 @@ void EPZSDelete (void)
   if (params->EPZSSpatialMem)
   {
 #if EPZSREF
+    free_mem5Dmv (EPZS_Motion);
     free_mem6Dshort (EPZSMotion);
 #else
+    free_mem4Dmv (EPZS_Motion);
     free_mem5Dshort (EPZSMotion);
 #endif
   }
@@ -497,9 +542,7 @@ void EPZSDelete (void)
 *    EPZS Slice Level Initialization
 ************************************************************************
 */
-void
-EPZSSliceInit (EPZSColocParams * p,
-               StorablePicture ** listX[6])
+void EPZSSliceInit (InputParameters *params, ImageParameters *img, EPZSColocParams * p, StorablePicture ** listX[6])
 {
   StorablePicture *fs, *fs_top, *fs_bottom;
   StorablePicture *fs1, *fs_top1, *fs_bottom1, *fsx;
@@ -519,12 +562,12 @@ EPZSSliceInit (EPZSColocParams * p,
     {
       for (i = 0; i < listXsize[j]; i++)
       {
-        if (j/2 == 0)
+        if ((j >> 1) == 0)
         {
           iTRb = iClip3 (-128, 127, enc_picture->poc - listX[j][i]->poc);
           iTRp = iClip3 (-128, 127, enc_picture->poc - listX[j][k]->poc);
         }
-        else if (j/2 == 1)
+        else if ((j >> 1) == 1)
         {
           iTRb = iClip3 (-128, 127, enc_picture->top_poc - listX[j][i]->poc);
           iTRp = iClip3 (-128, 127, enc_picture->top_poc - listX[j][k]->poc);
@@ -584,6 +627,7 @@ EPZSSliceInit (EPZSColocParams * p,
           prescale = 256;
         epzs_scale[0][j][i] = rshift_rnd_sf((mv_scale[j][0][i] * prescale), 8);
         epzs_scale[0][j + 1][i] = prescale - 256;
+        
         if (listXsize[list + j]>1)
         {
           iTRp = iClip3 (-128, 127, listX[list + j][1]->poc - listX[LIST_0 + j][i]->poc);
@@ -635,107 +679,157 @@ EPZSSliceInit (EPZSColocParams * p,
       }
     }
 
-    //if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
     if (!active_sps->frame_mbs_only_flag)
     {
-      for (j = 0; j < fs->size_y >> 2; j++)
+      if (img->MbaffFrameFlag)
       {
-        jj = j / 2;
-        jdiv = j / 2 + 4 * (j / 8);
-        for (i = 0; i < fs->size_x >> 2; i++)
+        for (j = 0; j < fs->size_y >> 2; j++)
         {
-          if (img->MbaffFrameFlag && fs->field_frame[j][i])
+          jj = j >> 1;
+          jdiv = jj + 4 * (j >> 3);
+
+          for (i = 0; i < fs->size_x >> 2; i++)
           {
-            //! Assign frame buffers for field MBs
-            //! Check whether we should use top or bottom field mvs.
-            //! Depending on the assigned poc values.
-            if (iabs (enc_picture->poc - fs_bottom->poc) > iabs (enc_picture->poc - fs_top->poc))
+            if (fs->motion.field_frame[j][i])
             {
-              tempmv_scale[LIST_0] = 256;
-              tempmv_scale[LIST_1] = 0;
-
-              if (fs->ref_id [LIST_0][jdiv][i] < 0 && listXsize[LIST_0] > 1)
+              //! Assign frame buffers for field MBs
+              //! Check whether we should use top or bottom field mvs.
+              //! Depending on the assigned poc values.
+              if (iabs (enc_picture->poc - fs_bottom->poc) > iabs (enc_picture->poc - fs_top->poc))
               {
-                fsx = fs_top1;
-                loffset = 1;
-              }
-              else
-              {
-                fsx = fs_top;
-                loffset = 0;
-              }
+                tempmv_scale[LIST_0] = 256;
+                tempmv_scale[LIST_1] = 0;
 
-              if (fs->ref_id [LIST_0][jdiv][i] != -1)
-              {
-                for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
+                if (fs->motion.ref_id [LIST_0][jdiv][i] < 0 && listXsize[LIST_0] > 1)
+                {
+                  fsx = fs_top1;
+                  loffset = 1;
+                }
+                else
                 {
-                  if (enc_picture->ref_pic_num[LIST_0][iref]==fs->ref_id [LIST_0][jdiv][i])
+                  fsx = fs_top;
+                  loffset = 0;
+                }
+
+                if (fs->motion.ref_id [LIST_0][jdiv][i] != -1)
+                {
+                  for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
                   {
-                    tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
-                    tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
-                    break;
+                    if (enc_picture->ref_pic_num[LIST_0][iref]==fs->motion.ref_id [LIST_0][jdiv][i])
+                    {
+                      tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
+                      tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
+                      break;
+                    }
                   }
+                  p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                }
+                else
+                {
+                  p->frame[LIST_0][j][i].mv_x = 0;
+                  p->frame[LIST_0][j][i].mv_y = 0;
+                  p->frame[LIST_1][j][i].mv_x = 0;
+                  p->frame[LIST_1][j][i].mv_y = 0;
                 }
-                p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][jj][i][0]), invmv_precision));
-                p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][jj][i][1]), invmv_precision));
-                p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][jj][i][0]), invmv_precision));
-                p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][jj][i][1]), invmv_precision));
               }
               else
               {
-                p->mv[LIST_0][j][i][0] = 0;
-                p->mv[LIST_0][j][i][1] = 0;
-                p->mv[LIST_1][j][i][0] = 0;
-                p->mv[LIST_1][j][i][1] = 0;
-              }
+                tempmv_scale[LIST_0] = 256;
+                tempmv_scale[LIST_1] = 0;
+
+                if (fs->motion.ref_id [LIST_0][jdiv + 4][i] < 0 && listXsize[LIST_0] > 1)
+                {
+                  fsx = fs_bottom1;
+                  loffset = 1;
+                }
+                else
+                {
+                  fsx = fs_bottom;
+                  loffset = 0;
+                }
 
+                if (fs->motion.ref_id [LIST_0][jdiv + 4][i] != -1)
+                {
+                  for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
+                  {
+                    if (enc_picture->ref_pic_num[LIST_0][iref]==fs->motion.ref_id [LIST_0][jdiv + 4][i])
+                    {
+                      tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
+                      tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
+                      break;
+                    }
+                  }
+                  p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                }
+                else
+                {
+                  p->frame[LIST_0][j][i].mv_x = 0;
+                  p->frame[LIST_0][j][i].mv_y = 0;
+                  p->frame[LIST_1][j][i].mv_x = 0;
+                  p->frame[LIST_1][j][i].mv_y = 0;
+                }
+              }
             }
             else
             {
               tempmv_scale[LIST_0] = 256;
               tempmv_scale[LIST_1] = 0;
-
-              if (fs->ref_id [LIST_0][jdiv + 4][i] < 0 && listXsize[LIST_0] > 1)
+              if (fs->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
               {
-                fsx = fs_bottom1;
+                fsx = fs1;
                 loffset = 1;
               }
               else
               {
-                fsx = fs_bottom;
+                fsx = fs;
                 loffset = 0;
               }
 
-              if (fs->ref_id [LIST_0][jdiv + 4][i] != -1)
+              if (fsx->motion.ref_id [LIST_0][j][i] != -1)
               {
                 for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
                 {
-                  if (enc_picture->ref_pic_num[LIST_0][iref]==fs->ref_id [LIST_0][jdiv + 4][i])
+                  if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->motion.ref_id [LIST_0][j][i])
                   {
                     tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
                     tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
                     break;
                   }
                 }
-                p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][jj][i][0]), invmv_precision));
-                p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][jj][i][1]), invmv_precision));
-                p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][jj][i][0]), invmv_precision));
-                p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][jj][i][1]), invmv_precision));
+                p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+                p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
               }
               else
               {
-                p->mv[LIST_0][j][i][0] = 0;
-                p->mv[LIST_0][j][i][1] = 0;
-                p->mv[LIST_1][j][i][0] = 0;
-                p->mv[LIST_1][j][i][1] = 0;
+                p->frame[LIST_0][j][i].mv_x = 0;
+                p->frame[LIST_0][j][i].mv_y = 0;
+                p->frame[LIST_1][j][i].mv_x = 0;
+                p->frame[LIST_1][j][i].mv_y = 0;
               }
             }
           }
-          else
+        }
+      }
+      else
+      {
+        for (j = 0; j < fs->size_y >> 2; j++)
+        {
+          jj = j >> 1;
+          jdiv = jj + 4 * (j >> 3);
+
+          for (i = 0; i < fs->size_x >> 2; i++)
           {
             tempmv_scale[LIST_0] = 256;
             tempmv_scale[LIST_1] = 0;
-            if (fs->ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+            if (fs->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
             {
               fsx = fs1;
               loffset = 1;
@@ -746,169 +840,169 @@ EPZSSliceInit (EPZSColocParams * p,
               loffset = 0;
             }
 
-            if (fsx->ref_id [LIST_0][j][i] != -1)
+            if (fsx->motion.ref_id [LIST_0][j][i] != -1)
             {
               for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
               {
-                if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->ref_id [LIST_0][j][i])
+                if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->motion.ref_id [LIST_0][j][i])
                 {
                   tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
                   tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
                   break;
                 }
               }
-              p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-              p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
+              p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+              p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+              p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+              p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = 0;
-              p->mv[LIST_0][j][i][1] = 0;
-              p->mv[LIST_1][j][i][0] = 0;
-              p->mv[LIST_1][j][i][1] = 0;
+              p->frame[LIST_0][j][i].mv_x = 0;
+              p->frame[LIST_0][j][i].mv_y = 0;
+              p->frame[LIST_1][j][i].mv_x = 0;
+              p->frame[LIST_1][j][i].mv_y = 0;
             }
           }
         }
       }
-    }
-
-    //! Generate field MVs from Frame MVs
-    if (img->structure || img->MbaffFrameFlag)
-    {
-      for (j = 0; j < fs->size_y / 8; j++)
+      
+      //! Generate field MVs from Frame MVs
+      if (img->structure || img->MbaffFrameFlag)
       {
-        for (i = 0; i < fs->size_x / 4; i++)
+        for (j = 0; j < fs->size_y / 8; j++)
         {
-          if (!img->MbaffFrameFlag)
+          for (i = 0; i < fs->size_x / 4; i++)
           {
-            tempmv_scale[LIST_0] = 256;
-            tempmv_scale[LIST_1] = 0;
-
-            if (fs->ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+            if (!img->MbaffFrameFlag)
             {
-              fsx = fs1;
-              loffset = 1;
-            }
-            else
-            {
-              fsx = fs;
-              loffset = 0;
-            }
+              tempmv_scale[LIST_0] = 256;
+              tempmv_scale[LIST_1] = 0;
 
-            if (fsx->ref_id [LIST_0][j][i] != -1)
-            {
-              for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
+              if (fs->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+              {
+                fsx = fs1;
+                loffset = 1;
+              }
+              else
+              {
+                fsx = fs;
+                loffset = 0;
+              }
+
+              if (fsx->motion.ref_id [LIST_0][j][i] != -1)
               {
-                if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->ref_id [LIST_0][j][i])
+                for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
                 {
-                  tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
-                  tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
-                  break;
+                  if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->motion.ref_id [LIST_0][j][i])
+                  {
+                    tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
+                    tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
+                    break;
+                  }
                 }
+                p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+                p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+              }
+              else
+              {
+                p->frame[LIST_0][j][i].mv_x = 0;
+                p->frame[LIST_0][j][i].mv_y = 0;
+                p->frame[LIST_1][j][i].mv_x = 0;
+                p->frame[LIST_1][j][i].mv_y = 0;
               }
-              p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-              p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
             }
             else
             {
-              p->mv[LIST_0][j][i][0] = 0;
-              p->mv[LIST_0][j][i][1] = 0;
-              p->mv[LIST_1][j][i][0] = 0;
-              p->mv[LIST_1][j][i][1] = 0;
-            }
-          }
-          else
-          {
-            tempmv_scale[LIST_0] = 256;
-            tempmv_scale[LIST_1] = 0;
+              tempmv_scale[LIST_0] = 256;
+              tempmv_scale[LIST_1] = 0;
 
-            if (fs_bottom->ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
-            {
-              fsx = fs_bottom1;
-              loffset = 1;
-            }
-            else
-            {
-              fsx = fs_bottom;
-              loffset = 0;
-            }
+              if (fs_bottom->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+              {
+                fsx = fs_bottom1;
+                loffset = 1;
+              }
+              else
+              {
+                fsx = fs_bottom;
+                loffset = 0;
+              }
 
-            if (fsx->ref_id [LIST_0][j][i] != -1)
-            {
-              for (iref = 0; iref < imin(2*img->num_ref_idx_l0_active,listXsize[LIST_0 + 4]); iref++)
+              if (fsx->motion.ref_id [LIST_0][j][i] != -1)
               {
-                if (enc_picture->ref_pic_num[LIST_0 + 4][iref]==fsx->ref_id [LIST_0][j][i])
+                for (iref = 0; iref < imin(2*img->num_ref_idx_l0_active,listXsize[LIST_0 + 4]); iref++)
                 {
-                  tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0 + 4][iref];
-                  tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1 + 4][iref];
-                  break;
+                  if (enc_picture->ref_pic_num[LIST_0 + 4][iref]==fsx->motion.ref_id [LIST_0][j][i])
+                  {
+                    tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0 + 4][iref];
+                    tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1 + 4][iref];
+                    break;
+                  }
                 }
+                p->bot[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->bot[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+                p->bot[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->bot[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+              }
+              else
+              {
+                p->bot[LIST_0][j][i].mv_x = 0;
+                p->bot[LIST_0][j][i].mv_y = 0;
+                p->bot[LIST_1][j][i].mv_x = 0;
+                p->bot[LIST_1][j][i].mv_y = 0;
               }
-              p->bottom_mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->bottom_mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-              p->bottom_mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->bottom_mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-            }
-            else
-            {
-              p->bottom_mv[LIST_0][j][i][0] = 0;
-              p->bottom_mv[LIST_0][j][i][1] = 0;
-              p->bottom_mv[LIST_1][j][i][0] = 0;
-              p->bottom_mv[LIST_1][j][i][1] = 0;
-            }
 
-            if (!fs->field_frame[2 * j][i])
-            {
-              p->bottom_mv[LIST_0][j][i][1] = (p->bottom_mv[LIST_0][j][i][1] + 1) >> 1;
-              p->bottom_mv[LIST_1][j][i][1] = (p->bottom_mv[LIST_1][j][i][1] + 1) >> 1;
-            }
+              if (!fs->motion.field_frame[2 * j][i])
+              {
+                p->bot[LIST_0][j][i].mv_y  = (p->bot[LIST_0][j][i].mv_y + 1) >> 1;
+                p->bot[LIST_1][j][i].mv_y  = (p->bot[LIST_1][j][i].mv_y + 1) >> 1;
+              }
 
-            tempmv_scale[LIST_0] = 256;
-            tempmv_scale[LIST_1] = 0;
+              tempmv_scale[LIST_0] = 256;
+              tempmv_scale[LIST_1] = 0;
 
-            if (fs_top->ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
-            {
-              fsx = fs_top1;
-              loffset = 1;
-            }
-            else
-            {
-              fsx = fs_top;
-              loffset = 0;
-            }
+              if (fs_top->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+              {
+                fsx = fs_top1;
+                loffset = 1;
+              }
+              else
+              {
+                fsx = fs_top;
+                loffset = 0;
+              }
 
-            if (fsx->ref_id [LIST_0][j][i] != -1)
-            {
-              for (iref = 0; iref < imin(2*img->num_ref_idx_l0_active,listXsize[LIST_0 + 2]); iref++)
+              if (fsx->motion.ref_id [LIST_0][j][i] != -1)
               {
-                if (enc_picture->ref_pic_num[LIST_0 + 2][iref]==fsx->ref_id [LIST_0][j][i])
+                for (iref = 0; iref < imin(2*img->num_ref_idx_l0_active,listXsize[LIST_0 + 2]); iref++)
                 {
-                  tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0 + 2][iref];
-                  tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1 + 2][iref];
-                  break;
+                  if (enc_picture->ref_pic_num[LIST_0 + 2][iref]==fsx->motion.ref_id [LIST_0][j][i])
+                  {
+                    tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0 + 2][iref];
+                    tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1 + 2][iref];
+                    break;
+                  }
                 }
+                p->top[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->top[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+                p->top[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+                p->top[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+              }
+              else
+              {
+                p->top[LIST_0][j][i].mv_x = 0;
+                p->top[LIST_0][j][i].mv_y = 0;
+                p->top[LIST_1][j][i].mv_x = 0;
+                p->top[LIST_1][j][i].mv_y = 0;
               }
-              p->top_mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->top_mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-              p->top_mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-              p->top_mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-            }
-            else
-            {
-              p->top_mv[LIST_0][j][i][0] = 0;
-              p->top_mv[LIST_0][j][i][1] = 0;
-              p->top_mv[LIST_1][j][i][0] = 0;
-              p->top_mv[LIST_1][j][i][1] = 0;
-            }
 
-            if (!fs->field_frame[2 * j][i])
-            {
-              p->top_mv[LIST_0][j][i][1] = rshift_rnd_sf((p->top_mv[LIST_0][j][i][1]), 1);
-              p->top_mv[LIST_1][j][i][1] = rshift_rnd_sf((p->top_mv[LIST_1][j][i][1]), 1);
+              if (!fs->motion.field_frame[2 * j][i])
+              {
+                p->top[LIST_0][j][i].mv_y  = (p->top[LIST_0][j][i].mv_y + 1) >> 1;
+                p->top[LIST_1][j][i].mv_y  = (p->top[LIST_1][j][i].mv_y + 1) >> 1;
+              }
             }
           }
         }
@@ -928,12 +1022,12 @@ EPZSSliceInit (EPZSColocParams * p,
           jdiv = (j>>1) + ((j>>3) << 2);
           for (i = 0; i < fs->size_x >> 2; i++)
           {
-            if (fs->field_frame[j][i])
+            if (fs->motion.field_frame[j][i])
             {
               tempmv_scale[LIST_0] = 256;
               tempmv_scale[LIST_1] = 0;
 
-              if (fs->ref_id [LIST_0][jdiv][i] < 0 && listXsize[LIST_0] > 1)
+              if (fs->motion.ref_id [LIST_0][jdiv][i] < 0 && listXsize[LIST_0] > 1)
               {
                 fsx = fs1;
                 loffset = 1;
@@ -943,11 +1037,11 @@ EPZSSliceInit (EPZSColocParams * p,
                 fsx = fs;
                 loffset = 0;
               }
-              if (fsx->ref_id [LIST_0][jdiv][i] != -1)
+              if (fsx->motion.ref_id [LIST_0][jdiv][i] != -1)
               {
                 for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
                 {
-                  if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->ref_id [LIST_0][jdiv][i])
+                  if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->motion.ref_id [LIST_0][jdiv][i])
                   {
                     tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
                     tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
@@ -957,25 +1051,25 @@ EPZSSliceInit (EPZSColocParams * p,
 
                 if (iabs (enc_picture->poc - fsx->bottom_field->poc) > iabs (enc_picture->poc - fsx->top_field->poc))
                 {
-                  p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->top_field->mv[LIST_0][jj][i][0]), invmv_precision));
-                  p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->top_field->mv[LIST_0][jj][i][1]), invmv_precision));
-                  p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->top_field->mv[LIST_0][jj][i][0]), invmv_precision));
-                  p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->top_field->mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->top_field->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->top_field->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->top_field->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->top_field->motion.mv[LIST_0][jj][i][1]), invmv_precision));
                 }
                 else
                 {
-                  p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->bottom_field->mv[LIST_0][jj][i][0]), invmv_precision));
-                  p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->bottom_field->mv[LIST_0][jj][i][1]), invmv_precision));
-                  p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->bottom_field->mv[LIST_0][jj][i][0]), invmv_precision));
-                  p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->bottom_field->mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->bottom_field->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->bottom_field->motion.mv[LIST_0][jj][i][1]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->bottom_field->motion.mv[LIST_0][jj][i][0]), invmv_precision));
+                  p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->bottom_field->motion.mv[LIST_0][jj][i][1]), invmv_precision));
                 }
               }
               else
               {
-                p->mv[LIST_0][j][i][0] = 0;
-                p->mv[LIST_0][j][i][1] = 0;
-                p->mv[LIST_1][j][i][0] = 0;
-                p->mv[LIST_1][j][i][1] = 0;
+                p->frame[LIST_0][j][i].mv_x = 0;
+                p->frame[LIST_0][j][i].mv_y = 0;
+                p->frame[LIST_1][j][i].mv_x = 0;
+                p->frame[LIST_1][j][i].mv_y = 0;
               }
             }
           }
@@ -991,7 +1085,7 @@ EPZSSliceInit (EPZSColocParams * p,
         {
           tempmv_scale[LIST_0] = 256;
           tempmv_scale[LIST_1] = 0;
-          if (fs->ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
+          if (fs->motion.ref_id [LIST_0][j][i] < 0 && listXsize[LIST_0] > 1)
           {
             fsx = fs1;
             loffset = 1;
@@ -1001,11 +1095,12 @@ EPZSSliceInit (EPZSColocParams * p,
             fsx = fs;
             loffset = 0;
           }
-          if (fsx->ref_id [LIST_0][j][i] != -1)
+         
+          if (fsx->motion.ref_id [LIST_0][j][i] != -1)
           {
             for (iref = 0; iref < imin(img->num_ref_idx_l0_active,listXsize[LIST_0]); iref++)
             {
-              if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->ref_id [LIST_0][j][i])
+              if (enc_picture->ref_pic_num[LIST_0][iref]==fsx->motion.ref_id [LIST_0][j][i])
               {
                 tempmv_scale[LIST_0] = epzs_scale[loffset][LIST_0][iref];
                 tempmv_scale[LIST_1] = epzs_scale[loffset][LIST_1][iref];
@@ -1013,17 +1108,17 @@ EPZSSliceInit (EPZSColocParams * p,
               }
             }
 
-            p->mv[LIST_0][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-            p->mv[LIST_0][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
-            p->mv[LIST_1][j][i][0] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][0]), invmv_precision));
-            p->mv[LIST_1][j][i][1] = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->mv[LIST_0][j][i][1]), invmv_precision));
+            p->frame[LIST_0][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+            p->frame[LIST_0][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_0] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
+            p->frame[LIST_1][j][i].mv_x = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][0]), invmv_precision));
+            p->frame[LIST_1][j][i].mv_y = iClip3 (-32768, 32767, rshift_rnd_sf((tempmv_scale[LIST_1] * fsx->motion.mv[LIST_0][j][i][1]), invmv_precision));
           }
           else
           {
-            p->mv[LIST_0][j][i][0] = 0;
-            p->mv[LIST_0][j][i][1] = 0;
-            p->mv[LIST_1][j][i][0] = 0;
-            p->mv[LIST_1][j][i][1] = 0;
+            p->frame[LIST_0][j][i].mv_x = 0;
+            p->frame[LIST_0][j][i].mv_y = 0;
+            p->frame[LIST_1][j][i].mv_x = 0;
+            p->frame[LIST_1][j][i].mv_y = 0;
           }
         }
       }
@@ -1035,15 +1130,15 @@ EPZSSliceInit (EPZSColocParams * p,
       {
         for (i = 0; i < fs->size_x >> 2; i++)
         {
-          if ((!img->MbaffFrameFlag && !img->structure && fs->field_frame[j][i]) || (img->MbaffFrameFlag && fs->field_frame[j][i]))
+          if ((!img->MbaffFrameFlag && !img->structure && fs->motion.field_frame[j][i]) || (img->MbaffFrameFlag && fs->motion.field_frame[j][i]))
           {
-            p->mv[LIST_0][j][i][1] *= 2;
-            p->mv[LIST_1][j][i][1] *= 2;
+            p->frame[LIST_0][j][i].mv_y *= 2; 
+            p->frame[LIST_1][j][i].mv_y *= 2;
           }
-          else if (img->structure && !fs->field_frame[j][i])
+          else if (img->structure && !fs->motion.field_frame[j][i])
           {
-            p->mv[LIST_0][j][i][1] = rshift_rnd_sf((p->mv[LIST_0][j][i][1]), 1);
-            p->mv[LIST_1][j][i][1] = rshift_rnd_sf((p->mv[LIST_1][j][i][1]), 1);
+            p->frame[LIST_0][j][i].mv_y = rshift_rnd_sf(p->frame[LIST_0][j][i].mv_y, 1);
+            p->frame[LIST_1][j][i].mv_y = rshift_rnd_sf(p->frame[LIST_1][j][i].mv_y, 1);
           }
         }
       }
@@ -1264,6 +1359,7 @@ static void EPZSSpatialMemPredictors (int list,
 {
 #if EPZSREF
   short ***mv = EPZSMotion[list][ref][blocktype];
+  //MotionVector ***prd_mv = &EPZS_Motion[list][ref][blocktype];
   MotionVector *cur_mv = &predictor->point[*prednum].motion;
 
   // Left Predictor
@@ -1271,7 +1367,6 @@ static void EPZSSpatialMemPredictors (int list,
   {
     cur_mv->mv_x = mv[by][pic_x - bs_x][0];
     cur_mv->mv_y = mv[by][pic_x - bs_x][1];
-    //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
     *prednum += (*((int*) cur_mv) != 0);
     cur_mv = &predictor->point[*prednum].motion;
   }
@@ -1280,7 +1375,6 @@ static void EPZSSpatialMemPredictors (int list,
   // Up predictor  
   cur_mv->mv_x = mv[by][pic_x][0];
   cur_mv->mv_y = mv[by][pic_x][1];
-  //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
   *prednum += (*((int*) cur_mv) != 0);
 
   // Up-Right predictor
@@ -1289,13 +1383,13 @@ static void EPZSSpatialMemPredictors (int list,
     cur_mv = &predictor->point[*prednum].motion;
     cur_mv->mv_x = mv[by][pic_x + bs_x][0];
     cur_mv->mv_y = mv[by][pic_x + bs_x][1];
-    //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
     *prednum += (*((int*) cur_mv) != 0);
   }
 
 #else
   int mot_scale = mv_scale[list][ref][0];
   short **mv = EPZSMotion[list][blocktype];
+  MotionVector **predictor = &EPZS_Motion[list][blocktype];
 
   // Left Predictor
   predictor->point[*prednum].motion.mv_x = (pic_x > 0)
@@ -1330,6 +1424,7 @@ static void EPZSSpatialMemPredictors (int list,
 #endif
 }
 
+
 /*!
 ***********************************************************************
 * \brief
@@ -1355,90 +1450,54 @@ EPZSTemporalPredictors (int list,         // <--  current list
                         int min_mcost)
 {
   int mvScale = mv_scale[list + list_offset][ref][0];
-  short ***col_mv = (list_offset == 0) ? EPZSCo_located->mv[list]
-    : (list_offset == 2) ? EPZSCo_located->top_mv[list] : EPZSCo_located->bottom_mv[list];
+  MotionVector **col_mv = (list_offset == 0) ? EPZSCo_located->frame[list]  
+    : (list_offset == 2) ? EPZSCo_located->top[list] : EPZSCo_located->bot[list];
   short temp_shift_mv = 8 + mv_rescale; // 16 - invmv_precision + mv_rescale
   MotionVector *cur_mv = &predictor->point[*prednum].motion;
 
-  cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x][0]), temp_shift_mv);
-  cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x][1]), temp_shift_mv);
-  //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-  *prednum += (*((int*) cur_mv) != 0);
-
+  *prednum += add_predictor(cur_mv, col_mv[o_block_y][o_block_x], mvScale, temp_shift_mv);
 
   if (min_mcost > stopCriterion && ref < 2)
   {
     if (block_available_left)
     {
-      cur_mv = &predictor->point[*prednum].motion;
-      cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x - 1][0]), temp_shift_mv);
-      cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x - 1][1]), temp_shift_mv);
-      //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-      *prednum += (*((int*) cur_mv) != 0);
+      *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y][o_block_x - 1], mvScale, temp_shift_mv);
 
       //Up_Left
       if (block_available_up)
       {
-        cur_mv = &predictor->point[*prednum].motion;
-        cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x - 1][0]), temp_shift_mv);
-        cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x - 1][1]), temp_shift_mv);
-        //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-        *prednum += (*((int*) cur_mv) != 0);
+        *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y - 1][o_block_x - 1], mvScale, temp_shift_mv);
       }
       //Down_Left
       if (block_available_below)
       {
-        cur_mv = &predictor->point[*prednum].motion;
-        cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x - 1][0]), temp_shift_mv);
-        cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x - 1][1]), temp_shift_mv);
-        //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-        *prednum += (*((int*) cur_mv) != 0);
+        *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y + blockshape_y][o_block_x - 1], mvScale, temp_shift_mv);
       }
     }
     // Up
     if (block_available_up)
     {
-      cur_mv = &predictor->point[*prednum].motion;
-      cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x][0]), temp_shift_mv);
-      cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x][1]), temp_shift_mv);
-      //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-      *prednum += (*((int*) cur_mv) != 0);
+      *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y - 1][o_block_x], mvScale, temp_shift_mv);
     }
 
     // Up - Right
     if (block_available_right)
     {
-      cur_mv = &predictor->point[*prednum].motion;
-      cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x + blockshape_x][0]), temp_shift_mv);
-      cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y][o_block_x + blockshape_x][1]), temp_shift_mv);
-      //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-      *prednum += (*((int*) cur_mv) != 0);
+      *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y][o_block_x + blockshape_x], mvScale, temp_shift_mv);
 
       if (block_available_up)
       {
-        cur_mv = &predictor->point[*prednum].motion;
-        cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x + blockshape_x][0]), temp_shift_mv);
-        cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y - 1][o_block_x + blockshape_x][1]), temp_shift_mv);
-        //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-        *prednum += (*((int*) cur_mv) != 0);
+        *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y - 1][o_block_x + blockshape_x], mvScale, temp_shift_mv);
       }
       if (block_available_below)
       {
-        cur_mv = &predictor->point[*prednum].motion;
-        cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x + blockshape_x][0]), temp_shift_mv);
-        cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x + blockshape_x][1]), temp_shift_mv);
-        //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-        *prednum += (*((int*) cur_mv) != 0);
+        *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y + blockshape_y][o_block_x + blockshape_x], mvScale, temp_shift_mv);
       }
     }
 
     if (block_available_below)
     {
-      cur_mv = &predictor->point[*prednum].motion;
-      cur_mv->mv_x = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x][0]), temp_shift_mv);
-      cur_mv->mv_y = rshift_rnd_sf((mvScale * col_mv[o_block_y + blockshape_y][o_block_x][1]), temp_shift_mv);
-      //*prednum += ((cur_mv->mv_x | cur_mv->mv_y) != 0);
-      *prednum += (*((int*) cur_mv) != 0);
+      *prednum += add_predictor( &predictor->point[*prednum].motion, col_mv[o_block_y + blockshape_y][o_block_x], mvScale, temp_shift_mv);
     }
   }
 }
@@ -1561,6 +1620,7 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
   int   second_mcost = INT_MAX;  
   int   *prevSad = EPZSDistortion[list + list_offset][blocktype - 1];
   short *motion=NULL;  
+  MotionVector *p_motion = NULL;
 
   short invalid_refs = 0;
   byte  checkMedian = FALSE;
@@ -1604,9 +1664,11 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
   if (params->EPZSSpatialMem)
   {
 #if EPZSREF
-    motion = EPZSMotion[list + list_offset][ref][blocktype - 1][block_y][pic_pix_x2];
+    motion   =  EPZSMotion [list + list_offset][ref][blocktype - 1][block_y][pic_pix_x2];
+    p_motion = &EPZS_Motion[list + list_offset][ref][blocktype - 1][block_y][pic_pix_x2];
 #else
-    motion = EPZSMotion[list + list_offset][blocktype - 1][block_y][pic_pix_x2];
+    motion   =  EPZSMotion [list + list_offset][blocktype - 1][block_y][pic_pix_x2];
+    p_motion = &EPZS_Motion[list + list_offset][blocktype - 1][block_y][pic_pix_x2];
 #endif
   }
 
@@ -1638,8 +1700,8 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
     {
       motion[0]  = tmp.mv_x;
       motion[1]  = tmp.mv_y;
+      *p_motion = tmp;
     }
-
     return min_mcost;
   }
 
@@ -1662,7 +1724,6 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
     int mb_available_right   = (img->mb_x < (img_width  >> 4) - 1);
     int mb_available_below   = (img->mb_y < (img_height >> 4) - 1);
 
-    int sadA, sadB, sadC;
     int block_available_right;
     int block_available_below;
     int prednum = 5;
@@ -1709,15 +1770,7 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
     }
     block_available_below = (mb_y + blocksize_y != MB_BLOCK_SIZE) || (mb_available_below);
 
-    sadA = block_a.available ? prevSad[pic_pix_x2 - blockshape_x] : INT_MAX;
-    sadB = block_b.available ? prevSad[pic_pix_x2] : INT_MAX;
-    sadC = block_c.available ? prevSad[pic_pix_x2 + blockshape_x] : INT_MAX;
-
-    stopCriterion = imin(sadA,imin(sadB,sadC));
-    stopCriterion = imax(stopCriterion,minthres[blocktype]);
-    stopCriterion = imin(stopCriterion,maxthres[blocktype]);
-
-    stopCriterion = (9 * imax (medthres[blocktype], stopCriterion) + 2 * medthres[blocktype]) >> 3;
+    stopCriterion = EPZSDetermineStopCriterion(prevSad, &block_a, &block_b, &block_c, pic_pix_x2, blocktype, blockshape_x);
 
     //! Add Spatial Predictors in predictor list.
     //! Scheme adds zero, left, top-left, top, top-right. Note that top-left adds very little
@@ -1762,7 +1815,7 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
     conditionEPZS = (ref == 0 || (ref > 0 && min_mcost > stopCriterion));
     // above seems to result in memory leak issues which need to be resolved
 
-    if (conditionEPZS && img->current_mb_nr != 0)
+    if (conditionEPZS && img->current_mb_nr != 0 && params->EPZSBlockType)
       EPZSBlockTypePredictors (block_x, block_y, blocktype, ref, list, predictor, &prednum);
 
     //! Check all predictors
@@ -1916,8 +1969,9 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
           if (params->EPZSSpatialMem && ref == 0)
 #endif
           {
-            motion[0]  = tmp.mv_x;
-            motion[1]  = tmp.mv_y;
+            motion[0] = tmp.mv_x;
+            motion[1] = tmp.mv_y;
+            *p_motion  = tmp;
           }
 
           return min_mcost;
@@ -1961,8 +2015,11 @@ EPZSPelBlockMotionSearch (Macroblock *currMB, // <--  current Macroblock
   if (params->EPZSSpatialMem && ref == 0)
 #endif
   {
-    motion[0]  = tmp.mv_x;
-    motion[1]  = tmp.mv_y;
+    motion[0] = tmp.mv_x;
+    motion[1] = tmp.mv_y;
+    *p_motion = tmp;
+    //printf("value %d %d %d %d\n", p_motion->mv_x, p_motion->mv_y, EPZS_Motion[list + list_offset][ref][0][0][0].mv_x, EPZS_Motion[list + list_offset][ref][0][0][0].mv_y);
+    //printf("xxxxx %d %d %d %d\n", p_motion->mv_x, p_motion->mv_y, EPZS_Motion[list + list_offset][ref][blocktype - 1][block_y][pic_pix_x2].mv_x, EPZS_Motion[list + list_offset][ref][blocktype - 1][block_y][pic_pix_x2].mv_y);
   }
 
   mv[0] = tmp.mv_x;
@@ -1995,8 +2052,10 @@ EPZSBiPredBlockMotionSearch (Macroblock *currMB,   // <--  Current Macroblock
                              short  static_mv[2],       // <--> in: search center (x|y) 
                              int    search_range,  // <--  1-d search range in pel units
                              int    min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                             int    iteration_no,  // <--  bi pred iteration number
                              int    lambda_factor, // <--  lagrangian parameter for determining motion cost
-                             int    apply_weights) // <--  perform weight based ME
+                             int    apply_weights  // <--  perform weight based ME
+                             )
 {
   StorablePicture *ref_picture1 = listX[list       + list_offset][ref];
   StorablePicture *ref_picture2 = listX[(list ^ 1) + list_offset][0];
@@ -2004,12 +2063,14 @@ EPZSBiPredBlockMotionSearch (Macroblock *currMB,   // <--  Current Macroblock
   short blocksize_x   = params->blc_size[blocktype][0];        // horizontal block size
   short mb_x = pic_pix_x - img->opix_x;
   short mb_y = pic_pix_y - img->opix_y;
-
+  short pic_pix_x2 = pic_pix_x >> 2;
+  //short pic_pix_y2 = pic_pix_y >> 2;
+  
   int stopCriterion = medthres[blocktype];
   int mapCenter_x = search_range - mv[0];
   int mapCenter_y = search_range - mv[1];
   int second_mcost = INT_MAX;
-
+  int *prevSad = EPZSBiDistortion[list + list_offset][blocktype - 1]; 
   short invalid_refs = 0;
   byte checkMedian = FALSE;
   EPZSStructure *searchPatternF = searchPattern;
@@ -2130,8 +2191,10 @@ EPZSBiPredBlockMotionSearch (Macroblock *currMB,   // <--  Current Macroblock
       else if (mb_x+blocksize_x == MB_BLOCK_SIZE)
         block_c.available = 0;
     }
+       
+    stopCriterion = EPZSDetermineStopCriterion(prevSad, &block_a, &block_b, &block_c, pic_pix_x2, blocktype, blocksize_x);
+    // stopCriterion = (11 * medthres[blocktype]) >> 3;
 
-    stopCriterion = (11 * medthres[blocktype]) >> 3;
 
     //! Add Spatial Predictors in predictor list.
     //! Scheme adds zero, left, top-left, top, top-right. Note that top-left adds very little
@@ -2310,6 +2373,11 @@ EPZSBiPredBlockMotionSearch (Macroblock *currMB,   // <--  Current Macroblock
       }
     }
   }
+  if (iteration_no == 0)
+  {
+    prevSad[pic_pix_x2] = min_mcost;
+  }
+  
   mv[0] = tmp.mv_x;
   mv[1] = tmp.mv_y;
   
@@ -2323,8 +2391,7 @@ return min_mcost;
 *    AMT/HYC
 ***********************************************************************
 */
-void
-EPZSOutputStats (FILE * stat, short stats_file)
+void EPZSOutputStats (InputParameters *params, FILE * stat, short stats_file)
 {
   if (stats_file == 1)
   {
diff --git a/lencod/src/me_fullfast.c b/lencod/src/me_fullfast.c
index 737119b..b10b925 100644
--- a/lencod/src/me_fullfast.c
+++ b/lencod/src/me_fullfast.c
@@ -189,8 +189,7 @@ ClearFastFullIntegerSearch ()
  *    (have to be called in start_macroblock())
  ***********************************************************************
  */
-void
-ResetFastFullIntegerSearch ()
+void ResetFastFullIntegerSearch ()
 {
   int list;
   for (list=0; list<2; list++)
@@ -326,6 +325,7 @@ void SetupFastFullPelSearch (Macroblock *currMb, short ref, int list)  // <--  r
   if (ChromaMEEnable)
   {
     imgpel *auxptr;
+    int   uv;
     int   bsx_c = BLOCK_SIZE >> (chroma_shift_x - 2);
     int   bsy_c = BLOCK_SIZE >> (chroma_shift_y - 2);
     int   pic_pix_x_c = img->opix_x >> (chroma_shift_x - 2);
@@ -333,9 +333,9 @@ void SetupFastFullPelSearch (Macroblock *currMb, short ref, int list)  // <--  r
 
     // copy the original cmp1 and cmp2 data to the orig_pic matrix
     // This seems to be wrong.
-    for (k=0; k<2; k++)
+    for (uv = 1; uv < 3; uv++)
     {
-      srcptr = auxptr = orig_pels + (256 << k);
+      srcptr = auxptr = orig_pels + (256 << (uv - 1));
       for ( pixel_y = 0, i = 0; i < (BLOCK_SIZE >> (chroma_shift_y - 2)); i++, pixel_y += bsy_c )
       {
         for ( pixel_x = 0, k = 0; k < (BLOCK_SIZE >> (chroma_shift_x - 2)); k++, pixel_x += bsx_c )
@@ -343,7 +343,7 @@ void SetupFastFullPelSearch (Macroblock *currMb, short ref, int list)  // <--  r
           srcptr = auxptr;
           for (j = 0; j < bsy_c; j++)
           {
-            memcpy( srcptr, &imgUV_org[k][pic_pix_y_c + pixel_y + j][pic_pix_x_c + pixel_x], bsx_c * sizeof(imgpel));
+            memcpy( srcptr, &pImgOrg[uv][pic_pix_y_c + pixel_y + j][pic_pix_x_c + pixel_x], bsx_c * sizeof(imgpel));
             srcptr += bsx_c;
           }
           auxptr += MB_BLOCK_SIZE;
@@ -389,7 +389,7 @@ void SetupFastFullPelSearch (Macroblock *currMb, short ref, int list)  // <--  r
   height_pad    = ref_picture->size_y_pad;
 
   //===== get search center: predictor of 16x16 block =====
-  SetMotionVectorPredictor (currMB, pmv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, 0, 0, 16, 16);
+  SetMotionVectorPredictor (currMB, pmv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, 0, 0, 16, 16);
 
   mv[0] = pmv[0] / 4;
   mv[1] = pmv[1] / 4;
@@ -543,7 +543,7 @@ void SetupFastFullPelSearch (Macroblock *currMB, short ref, int list)  // <--  r
   }
 
   //===== get search center: predictor of 16x16 block =====
-  SetMotionVectorPredictor (currMB, pmv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, 0, 0, 16, 16);
+  SetMotionVectorPredictor (currMB, pmv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, 0, 0, 16, 16);
 
   search_center_x[list][ref] = pmv[0] / 4;
   search_center_y[list][ref] = pmv[1] / 4;
@@ -573,11 +573,11 @@ void SetupFastFullPelSearch (Macroblock *currMB, short ref, int list)  // <--  r
   }
   if ( ChromaMEEnable)
   {
-    for (k = 0; k < 2; k++)
+    for (k = 1; k < 3; k++)
     {
       for   (y = img->opix_c_y; y < img->opix_c_y + img->mb_cr_size_y; y++)
       {
-        memcpy(srcptr, &imgUV_org[k][y][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
+        memcpy(srcptr, &pImgOrg[k][y][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
         srcptr += img->mb_cr_size_x;
       }
     }
diff --git a/lencod/src/me_fullsearch.c b/lencod/src/me_fullsearch.c
index d260199..ce03a9b 100644
--- a/lencod/src/me_fullsearch.c
+++ b/lencod/src/me_fullsearch.c
@@ -161,6 +161,7 @@ FullPelBlockMotionBiPred (Macroblock *currMB,      // <--  current Macroblock
                           short     static_mv[2],       // <--> in: search center (x|y) 
                           int       search_range,  // <--  1-d search range in pel units
                           int       min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                          int       iteration_no,  // <--  bi pred iteration number
                           int       lambda_factor, // <--  lagrangian parameter for determining motion cost
                           int       apply_weights  // <--  perform weight based ME
                           ) 
diff --git a/lencod/src/me_umhex.c b/lencod/src/me_umhex.c
index 2c72b6a..78a497a 100644
--- a/lencod/src/me_umhex.c
+++ b/lencod/src/me_umhex.c
@@ -31,6 +31,7 @@
 #include "refbuf.h"
 #include "mb_access.h"
 #include "image.h"
+#include "enc_statistics.h"
 #include "me_distortion.h"
 
 #define Q_BITS          15
@@ -63,15 +64,7 @@ static int Median_Pred_Thd_MB[8];
 static int Big_Hexagon_Thd_MB[8];
 static int Multi_Ref_Thd_MB[8];
 
-
-static const int quant_coef[6][4][4] = {
-  {{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243},{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243}},
-  {{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660},{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660}},
-  {{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194},{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194}},
-  {{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647},{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647}},
-  {{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355},{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355}},
-  {{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893},{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893}}
-};
+extern const int quant_coef[6][4][4];
 
 
 void UMHEX_DefineThreshold()
@@ -115,8 +108,8 @@ void UMHEX_DefineThreshold()
 
 void UMHEX_DefineThresholdMB()
 {
-  int gb_qp_per    = (params->qpN-MIN_QP)/6;
-  int gb_qp_rem    = (params->qpN-MIN_QP)%6;
+  int gb_qp_per    = (params->qpN)/6;
+  int gb_qp_rem    = (params->qpN)%6;
 
   int gb_q_bits    = Q_BITS+gb_qp_per;
   int gb_qp_const,Thresh4x4;
@@ -833,7 +826,7 @@ void UMHEX_setup(short ref, int list, int block_y, int block_x, int blocktype, s
   int temp_blocktype = 0;
   int indication_blocktype[8]={0,0,1,1,2,4,4,5};
   N_Bframe = params->successive_Bframe;
-  n_Bframe =(N_Bframe) ? (frame_ctr[B_SLICE]%(N_Bframe+1)): 0;
+  n_Bframe =(N_Bframe) ? (stats->frame_ctr[B_SLICE]%(N_Bframe+1)): 0;
 
 
   /**************************** MV prediction **********************/
@@ -961,6 +954,7 @@ UMHEXBipredIntegerPelBlockMotionSearch (Macroblock *currMB,      // <--  current
                                         short     s_mv[2],       // <--> in: search center (x|y) / out: motion vector (x|y) - in pel units
                                         int       search_range,  // <--  1-d search range in pel units
                                         int       min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                                        int       iteration_no,  // <--  bi pred iteration number
                                         int       lambda_factor, // <--  lagrangian parameter for determining motion cost
                                         int       apply_weights
                                         )
@@ -1132,9 +1126,9 @@ UMHEXBipredIntegerPelBlockMotionSearch (Macroblock *currMB,      // <--  current
   {
     int  N_Bframe=0;
     int  n_Bframe=0;
-    short****** bipred_mv = list ? img->bipred_mv1 : img->bipred_mv2;
+    short****** bipred_mv = img->bipred_mv[list];
     N_Bframe = params->successive_Bframe;
-    n_Bframe = frame_ctr[B_SLICE]%(N_Bframe+1);
+    n_Bframe = stats->frame_ctr[B_SLICE]%(N_Bframe+1);
 
 
     /**************************** MV prediction **********************/
diff --git a/lencod/src/me_umhexsmp.c b/lencod/src/me_umhexsmp.c
index f11a9bb..2fec1ad 100644
--- a/lencod/src/me_umhexsmp.c
+++ b/lencod/src/me_umhexsmp.c
@@ -865,6 +865,7 @@ smpUMHEXBipredIntegerPelBlockMotionSearch (Macroblock *currMB, // <--  current M
                                            short     s_mv[2],       // <--> in: search center (x|y) 
                                            int       search_range,  // <--  1-d search range in pel units
                                            int       min_mcost,     // <--  minimum motion cost (cost for center or huge value)
+                                           int       iteration_no,  // <--  bi pred iteration number
                                            int       lambda_factor, // <--  lagrangian parameter for determining motion cost
                                            int       apply_weights
                                            )
diff --git a/lencod/src/memalloc.c b/lencod/src/memalloc.c
index 2507225..3ddd21b 100644
--- a/lencod/src/memalloc.c
+++ b/lencod/src/memalloc.c
@@ -55,6 +55,326 @@ void free_top_bot_planes(imgpel **imgTopField, imgpel **imgBotField)
   free (imgBotField);
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 2D memory array -> LambdaParams array2D[rows][columns]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************/
+int get_mem2Dlm(LambdaParams ***array2D, int dim0, int dim1)
+{
+  int i;
+
+  if((*array2D    = (LambdaParams**)calloc(dim0,       sizeof(LambdaParams*))) == NULL)
+    no_mem_exit("get_mem2Dlm: array2D");
+  if((*(*array2D) = (LambdaParams* )calloc(dim0 * dim1,sizeof(LambdaParams ))) == NULL)
+    no_mem_exit("get_mem2Dlm: array2D");
+
+  for(i = 1 ; i < dim0; i++)
+    (*array2D)[i] =  (*array2D)[i-1] + dim1;
+
+  return dim0 * dim1 * sizeof(LambdaParams);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 2D memory array
+ *    which was allocated with get_mem2Dlm()
+ ************************************************************************
+ */
+void free_mem2Dlm(LambdaParams **array2D)
+{
+  if (array2D)
+  {
+    if (*array2D)
+      free (*array2D);
+    else 
+      error ("free_mem2Dlm: trying to free unused memory",100);
+
+    free (array2D);
+  } 
+  else
+  {
+    error ("free_mem2Dlm: trying to free unused memory",100);
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 2D memory array -> PicMotionParams2 array2D[rows][columns]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************/
+int get_mem2Dmp(PicMotionParams2 ***array2D, int dim0, int dim1)
+{
+  int i;
+
+  if((*array2D    = (PicMotionParams2**)calloc(dim0,       sizeof(PicMotionParams2*))) == NULL)
+    no_mem_exit("get_mem2Dmv: array2D");
+  if((*(*array2D) = (PicMotionParams2* )calloc(dim0 * dim1,sizeof(PicMotionParams2 ))) == NULL)
+    no_mem_exit("get_mem2Dmp: array2D");
+
+  for(i = 1 ; i < dim0; i++)
+    (*array2D)[i] =  (*array2D)[i-1] + dim1;
+
+  return dim0 * dim1 * sizeof(PicMotionParams2);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 3D memory array -> PicMotionParams2 array3D[frames][rows][columns]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************
+ */
+int get_mem3Dmp(PicMotionParams2 ****array3D, int dim0, int dim1, int dim2)
+{
+  int i;
+
+  if(((*array3D) = (PicMotionParams2***)calloc(dim0,sizeof(PicMotionParams2**))) == NULL)
+    no_mem_exit("get_mem3Dmp: array3D");
+
+  get_mem2Dmp(*array3D, dim0 * dim1, dim2);
+
+  for(i = 1; i < dim0; i++)
+    (*array3D)[i] = (*array3D)[i - 1] + dim1;
+  
+  return dim0 * dim1 * dim2 * sizeof(PicMotionParams2);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 2D memory array
+ *    which was allocated with get_mem2Dmp()
+ ************************************************************************
+ */
+void free_mem2Dmp(PicMotionParams2 **array2D)
+{
+  if (array2D)
+  {
+    if (*array2D)
+      free (*array2D);
+    else 
+      error ("free_mem2Dmp: trying to free unused memory",100);
+
+    free (array2D);
+  } 
+  else
+  {
+    error ("free_mem2Dmp: trying to free unused memory",100);
+  }
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 3D memory array
+ *    which was allocated with get_mem3Dmp()
+ ************************************************************************
+ */
+void free_mem3Dmp(PicMotionParams2 ***array3D)
+{
+  if (array3D)
+  {
+    free_mem2Dmp(*array3D);
+    free (array3D);
+  }
+  else
+  {
+    error ("free_mem3Dmp: trying to free unused memory",100);
+  }
+}
+
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 2D memory array -> MotionVector array2D[rows][columns]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************/
+int get_mem2Dmv(MotionVector ***array2D, int dim0, int dim1)
+{
+  int i;
+
+  if((*array2D    = (MotionVector**)calloc(dim0,       sizeof(MotionVector*))) == NULL)
+    no_mem_exit("get_mem2Dmv: array2D");
+  if((*(*array2D) = (MotionVector* )calloc(dim0 * dim1,sizeof(MotionVector ))) == NULL)
+    no_mem_exit("get_mem2Dmv: array2D");
+
+  for(i = 1 ; i < dim0; i++)
+    (*array2D)[i] =  (*array2D)[i-1] + dim1;
+
+  return dim0 * dim1 * sizeof(MotionVector);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 3D memory array -> MotionVector array3D[frames][rows][columns]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************
+ */
+int get_mem3Dmv(MotionVector ****array3D, int dim0, int dim1, int dim2)
+{
+  int i;
+
+  if(((*array3D) = (MotionVector***)calloc(dim0,sizeof(MotionVector**))) == NULL)
+    no_mem_exit("get_mem3Dmv: array3D");
+
+  get_mem2Dmv(*array3D, dim0 * dim1, dim2);
+
+  for(i = 1; i < dim0; i++)
+    (*array3D)[i] = (*array3D)[i - 1] + dim1;
+  
+  return dim0 * dim1 * dim2 * sizeof(MotionVector);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 4D memory array -> MotionVector array3D[dim0][dim1][dim2][dim3]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************
+ */
+int get_mem4Dmv(MotionVector *****array4D, int dim0, int dim1, int dim2, int dim3)
+{
+  int i;
+
+  if(((*array4D) = (MotionVector****)calloc(dim0,sizeof(MotionVector***))) == NULL)
+    no_mem_exit("get_mem4Dpel: array4D");
+
+  get_mem3Dmv(*array4D, dim0 * dim1, dim2, dim3);
+
+  for(i = 1; i < dim0; i++)
+    (*array4D)[i] = (*array4D)[i - 1] + dim1;
+  
+  return dim0 * dim1 * dim2 * dim3 * sizeof(MotionVector);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 5D memory array -> MotionVector array3D[dim0][dim1][dim2][dim3][dim4]
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************
+ */
+int get_mem5Dmv(MotionVector ******array5D, int dim0, int dim1, int dim2, int dim3, int dim4)
+{
+  int i;
+
+  if(((*array5D) = (MotionVector*****)calloc(dim0,sizeof(MotionVector****))) == NULL)
+    no_mem_exit("get_mem5Dpel: array5D");
+
+  get_mem4Dmv(*array5D, dim0 * dim1, dim2, dim3, dim4);
+
+  for(i = 1; i < dim0; i++)
+    (*array5D)[i] = (*array5D)[i - 1] + dim1;
+  
+  return dim0 * dim1 * dim2 * dim3 * dim4 * sizeof(MotionVector);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 2D memory array
+ *    which was allocated with get_mem2Dmv()
+ ************************************************************************
+ */
+void free_mem2Dmv(MotionVector **array2D)
+{
+  if (array2D)
+  {
+    if (*array2D)
+      free (*array2D);
+    else 
+      error ("free_mem2Dmv: trying to free unused memory",100);
+
+    free (array2D);
+  } 
+  else
+  {
+    error ("free_mem2Dmv: trying to free unused memory",100);
+  }
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 3D memory array
+ *    which was allocated with get_mem3Dmv()
+ ************************************************************************
+ */
+void free_mem3Dmv(MotionVector ***array3D)
+{
+  if (array3D)
+  {
+    free_mem2Dmv(*array3D);
+    free (array3D);
+  }
+  else
+  {
+    error ("free_mem3Dmv: trying to free unused memory",100);
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 4D memory array
+ *    which was allocated with get_mem4Dmv()
+ ************************************************************************
+ */
+void free_mem4Dmv(MotionVector ****array4D)
+{
+  if (array4D)
+  {
+    free_mem3Dmv(*array4D);
+    free (array4D);
+  }
+  else
+  {
+    error ("free_mem4Dmv: trying to free unused memory",100);
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    free 5D memory array
+ *    which was allocated with get_mem5Dmv()
+ ************************************************************************
+ */
+void free_mem5Dmv(MotionVector *****array5D)
+{
+  if (array5D)
+  {
+    free_mem4Dmv(*array5D);
+    free (array5D);
+  }
+  else
+  {
+    error ("free_mem5Dmv: trying to free unused memory",100);
+  }
+}
 
 /*!
  ************************************************************************
@@ -164,7 +484,8 @@ void free_mem2Dpel(imgpel **array2D)
   {
     if (*array2D)
       free (*array2D);
-    else error ("free_mem2Dpel: trying to free unused memory",100);
+    else 
+      error ("free_mem2Dpel: trying to free unused memory",100);
 
     free (array2D);
   } 
@@ -914,14 +1235,14 @@ int get_mem2Ddouble(double ***array2D, int rows, int columns)
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem2Ddb_offset(double ***array2D, int rows, int columns, int offset)
+int get_mem2Dodouble(double ***array2D, int rows, int columns, int offset)
 {
   int i;
 
   if((*array2D      = (double**)calloc(rows,        sizeof(double*))) == NULL)
-    no_mem_exit("get_mem2Ddb_offset: array2D");
+    no_mem_exit("get_mem2Dodouble: array2D");
   if(((*array2D)[0] = (double* )calloc(rows*columns,sizeof(double ))) == NULL)
-    no_mem_exit("get_mem2Ddb_offset: array2D");
+    no_mem_exit("get_mem2Dodouble: array2D");
 
   (*array2D)[0] += offset;
 
@@ -940,15 +1261,15 @@ int get_mem2Ddb_offset(double ***array2D, int rows, int columns, int offset)
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem3Ddb_offset(double ****array3D, int rows, int columns, int pels, int offset)
+int get_mem3Dodouble(double ****array3D, int rows, int columns, int pels, int offset)
 {
   int  i,j;
 
   if(((*array3D) = (double***)calloc(rows,sizeof(double**))) == NULL)
-    no_mem_exit("get_mem3Ddb_offset: array3D");
+    no_mem_exit("get_mem3Dodouble: array3D");
 
   if(((*array3D)[0] = (double** )calloc(rows*columns,sizeof(double*))) == NULL)
-    no_mem_exit("get_mem3Ddb_offset: array3D");
+    no_mem_exit("get_mem3Dodouble: array3D");
 
   (*array3D) [0] += offset;
 
@@ -958,7 +1279,7 @@ int get_mem3Ddb_offset(double ****array3D, int rows, int columns, int pels, int
   for (i = 0; i < rows; i++)
     for (j = -offset; j < columns - offset; j++)
       if(((*array3D)[i][j] = (double* )calloc(pels,sizeof(double))) == NULL)
-        no_mem_exit("get_mem3Ddb_offset: array3D");
+        no_mem_exit("get_mem3Dodouble: array3D");
 
   return rows*columns*pels*sizeof(double);
 }
@@ -1005,15 +1326,15 @@ int get_offset_mem2Dshort(short ***array2D, int rows, int columns, int offset_y,
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int offset)
+int get_mem3Doint(int ****array3D, int rows, int columns, int pels, int offset)
 {
   int  i,j;
 
   if(((*array3D) = (int***)calloc(rows,sizeof(int**))) == NULL)
-    no_mem_exit("get_mem3Dint_offset: array3D");
+    no_mem_exit("get_mem3Doint: array3D");
 
   if(((*array3D)[0] = (int** )calloc(rows*columns,sizeof(int*))) == NULL)
-    no_mem_exit("get_mem3Dint_offset: array3D");
+    no_mem_exit("get_mem3Doint: array3D");
 
   (*array3D) [0] += offset;
 
@@ -1023,7 +1344,7 @@ int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int of
   for (i = 0; i < rows; i++)
     for (j = -offset; j < columns - offset; j++)
       if(((*array3D)[i][j] = (int* )calloc(pels,sizeof(int))) == NULL)
-        no_mem_exit("get_mem3Dint_offset: array3D");
+        no_mem_exit("get_mem3Doint: array3D");
 
   return rows*columns*pels*sizeof(int);
 }
@@ -1038,7 +1359,7 @@ int get_mem3Dint_offset(int ****array3D, int rows, int columns, int pels, int of
  *    memory size in bytes
  ************************************************************************
  */
-int get_mem2Dint_offset(int ***array2D, int rows, int columns, int offset)
+int get_mem2Doint(int ***array2D, int rows, int columns, int offset)
 {
   int i;
 
@@ -1118,20 +1439,20 @@ void free_mem2Ddouble(double **array2D)
 *    which was allocated with get_mem2Ddouble()
 ************************************************************************
 */
-void free_mem2Ddb_offset(double **array2D, int offset)
+void free_mem2Dodouble(double **array2D, int offset)
 {
   if (array2D)
   {
     array2D[0] -= offset;
     if (array2D[0])
       free (array2D[0]);
-    else error ("free_mem2Ddb_offset: trying to free unused memory",100);
+    else error ("free_mem2Dodouble: trying to free unused memory",100);
 
     free (array2D);
 
   } else
   {
-    error ("free_mem2Ddb_offset: trying to free unused memory",100);
+    error ("free_mem2Dodouble: trying to free unused memory",100);
   }
 }
 
@@ -1141,7 +1462,7 @@ void free_mem2Ddb_offset(double **array2D, int offset)
  *    free 3D memory array with offset
  ************************************************************************
  */
-void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
+void free_mem3Dodouble(double ***array3D, int rows, int columns, int offset)
 {
   int i, j;
 
@@ -1154,19 +1475,19 @@ void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
         if (array3D[i][j])
           free(array3D[i][j]);
         else
-          error ("free_mem3Ddb_offset: trying to free unused memory",100);
+          error ("free_mem3Dodouble: trying to free unused memory",100);
       }
     }
     array3D[0] -= offset;
     if (array3D[0])
       free(array3D[0]);
     else
-      error ("free_mem3Ddb_offset: trying to free unused memory",100);
+      error ("free_mem3Dodouble: trying to free unused memory",100);
     free (array3D);
   }
   else
   {
-    error ("free_mem3Ddb_offset: trying to free unused memory",100);
+    error ("free_mem3Dodouble: trying to free unused memory",100);
   }
 }
 
@@ -1176,7 +1497,7 @@ void free_mem3Ddb_offset(double ***array3D, int rows, int columns, int offset)
  *    free 3D memory array with offset
  ************************************************************************
  */
-void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
+void free_mem3Doint(int ***array3D, int rows, int columns, int offset)
 {
   int i, j;
 
@@ -1189,19 +1510,19 @@ void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
         if (array3D[i][j])
           free(array3D[i][j]);
         else
-          error ("free_mem3Dint_offset: trying to free unused memory",100);
+          error ("free_mem3Doint: trying to free unused memory",100);
       }
     }
     array3D[0] -= offset;
     if (array3D[0])
       free(array3D[0]);
     else
-      error ("free_mem3Dint_offset: trying to free unused memory",100);
+      error ("free_mem3Doint: trying to free unused memory",100);
     free (array3D);
   }
   else
   {
-    error ("free_mem3Dint_offset: trying to free unused memory",100);
+    error ("free_mem3Doint: trying to free unused memory",100);
   }
 }
 
@@ -1213,7 +1534,7 @@ void free_mem3Dint_offset(int ***array3D, int rows, int columns, int offset)
 *    which was allocated with get_mem2Ddouble()
 ************************************************************************
 */
-void free_mem2Dint_offset(int **array2D, int offset)
+void free_mem2Doint(int **array2D, int offset)
 {
   if (array2D)
   {
@@ -1221,14 +1542,14 @@ void free_mem2Dint_offset(int **array2D, int offset)
     if (array2D[0])
       free (array2D[0]);
     else 
-      error ("free_mem2Dint_offset: trying to free unused memory",100);
+      error ("free_mem2Doint: trying to free unused memory",100);
 
     free (array2D);
 
   } 
   else
   {
-    error ("free_mem2Dint_offset: trying to free unused memory",100);
+    error ("free_mem2Doint: trying to free unused memory",100);
   }
 }
 
@@ -1278,3 +1599,58 @@ void free_mem3Ddouble(double ***array3D)
 	}
 }
 
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocate 2D memory array -> LambdaParams array2D[rows][columns]
+ *    Note that array is shifted towards offset allowing negative values
+ *
+ * \par Output:
+ *    memory size in bytes
+ ************************************************************************
+ */
+int get_mem2Dolm(LambdaParams ***array2D, int rows, int columns, int offset)
+{
+  int i;
+
+  if((*array2D      = (LambdaParams**) calloc(rows, sizeof(LambdaParams*))) == NULL)
+    no_mem_exit("get_mem2Dolm: array2D");
+  if(((*array2D)[0] = (LambdaParams* ) calloc(rows*columns,sizeof(LambdaParams))) == NULL)
+    no_mem_exit("get_mem2Dolm: array2D");
+
+  (*array2D)[0] += offset;
+
+  for(i=1 ; i<rows ; i++)
+    (*array2D)[i] =  (*array2D)[i-1] + columns  ;
+
+  return rows*columns*sizeof(LambdaParams);
+}
+
+
+/*!
+************************************************************************
+* \brief
+*    free 2D LambdaParams memory array (with offset)
+*    which was allocated with get_mem2Dlm()
+************************************************************************
+*/
+void free_mem2Dolm(LambdaParams **array2D, int offset)
+{
+  if (array2D)
+  {
+    array2D[0] -= offset;
+    if (array2D[0])
+      free (array2D[0]);
+    else 
+      error ("free_mem2Dolm: trying to free unused memory",100);
+
+    free (array2D);
+
+  } 
+  else
+  {
+    error ("free_mem2Dolm: trying to free unused memory",100);
+  }
+}
+
diff --git a/lencod/src/mode_decision.c b/lencod/src/mode_decision.c
index 62f46b7..6321f2c 100644
--- a/lencod/src/mode_decision.c
+++ b/lencod/src/mode_decision.c
@@ -26,6 +26,7 @@
 #include "me_umhexsmp.h"
 #include "macroblock.h"
 #include "rdo_quant.h"
+#include "errdo.h"
 
 
 //==== MODULE PARAMETERS ====
@@ -54,7 +55,6 @@ void reset_valid_modes(RD_PARAMS *enc_mb)
 */
 void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bslice)
 {
-  int mode;
   int l,k;
 
   //Setup list offset
@@ -62,9 +62,9 @@ void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bs
   enc_mb->list_offset[LIST_1] = LIST_1 + currMB->list_offset;
 
   enc_mb->curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
-
+ 
   // Set valid modes  
-  enc_mb->valid[I8MB]  = (!params->DisableIntraInInter || intra )? params->Transform8x8Mode : 0;
+  enc_mb->valid[I8MB]  = (!params->DisableIntraInInter || intra )?   params->Transform8x8Mode : 0;
   enc_mb->valid[I4MB]  = (!params->DisableIntraInInter || intra )? ((params->Transform8x8Mode == 2) ? 0 : 1) : 0;
   enc_mb->valid[I4MB]  = (!params->DisableIntra4x4  ) ? enc_mb->valid[I4MB] : 0;
   enc_mb->valid[I16MB] = (!params->DisableIntraInInter || intra )? 1 : 0;
@@ -81,7 +81,7 @@ void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bs
   enc_mb->valid[7]     = (!intra && params->InterSearch[bslice][7] && !(params->Transform8x8Mode==2));
   enc_mb->valid[P8x8]  = (enc_mb->valid[4] || enc_mb->valid[5] || enc_mb->valid[6] || enc_mb->valid[7]);
   enc_mb->valid[12]    = (img->type == SI_SLICE);
-
+  
   if (params->UseRDOQuant && params->RDOQ_CP_Mode && (img->qp != img->masterQP) )  
     RDOQ_update_mode(enc_mb, bslice);
 
@@ -122,63 +122,28 @@ void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bs
   // computations and cleanup code.
   if (bslice && img->nal_reference_idc)
   {
-    enc_mb->lambda_md = img->lambda_md[5][img->qp];
+    enc_mb->lambda_md = img->lambda_md[5][img->masterQP];
 
-    enc_mb->lambda_me[F_PEL] = img->lambda_me[5][img->qp][F_PEL];
-    enc_mb->lambda_me[H_PEL] = img->lambda_me[5][img->qp][H_PEL];
-    enc_mb->lambda_me[Q_PEL] = img->lambda_me[5][img->qp][Q_PEL];
-
-    enc_mb->lambda_mf[F_PEL] = img->lambda_mf[5][img->qp][F_PEL];
-    enc_mb->lambda_mf[H_PEL] = img->lambda_mf[5][img->qp][H_PEL];
-    enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[5][img->qp][Q_PEL];
+    enc_mb->lambda_me[F_PEL] = img->lambda_me[5][img->masterQP][F_PEL];
+    enc_mb->lambda_me[H_PEL] = img->lambda_me[5][img->masterQP][H_PEL];
+    enc_mb->lambda_me[Q_PEL] = img->lambda_me[5][img->masterQP][Q_PEL];
 
+    enc_mb->lambda_mf[F_PEL] = img->lambda_mf[5][img->masterQP][F_PEL];
+    enc_mb->lambda_mf[H_PEL] = img->lambda_mf[5][img->masterQP][H_PEL];
+    enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[5][img->masterQP][Q_PEL];
   }
   else
   {
-    enc_mb->lambda_md = img->lambda_md[img->type][img->qp];
-
-    enc_mb->lambda_me[F_PEL] = img->lambda_me[img->type][img->qp][F_PEL];
-    enc_mb->lambda_me[H_PEL] = img->lambda_me[img->type][img->qp][H_PEL];
-    enc_mb->lambda_me[Q_PEL] = img->lambda_me[img->type][img->qp][Q_PEL];
-
-    enc_mb->lambda_mf[F_PEL] = img->lambda_mf[img->type][img->qp][F_PEL];
-    enc_mb->lambda_mf[H_PEL] = img->lambda_mf[img->type][img->qp][H_PEL];
-    enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[img->type][img->qp][Q_PEL];
+    enc_mb->lambda_md = img->lambda_md[img->type][img->masterQP];
+    enc_mb->lambda_me[F_PEL] = img->lambda_me[img->type][img->masterQP][F_PEL];
+    enc_mb->lambda_me[H_PEL] = img->lambda_me[img->type][img->masterQP][H_PEL];
+    enc_mb->lambda_me[Q_PEL] = img->lambda_me[img->type][img->masterQP][Q_PEL];
+
+    enc_mb->lambda_mf[F_PEL] = img->lambda_mf[img->type][img->masterQP][F_PEL];
+    enc_mb->lambda_mf[H_PEL] = img->lambda_mf[img->type][img->masterQP][H_PEL];
+    enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[img->type][img->masterQP][Q_PEL];
   }
-
-  if (params->UseRDOQuant)
-  {
-    if (bslice && img->nal_reference_idc)
-    { 
-      enc_mb->lambda_md = img->lambda_md[5][img->masterQP];
-
-      enc_mb->lambda_me[F_PEL] = img->lambda_me[5][img->masterQP][F_PEL];
-      enc_mb->lambda_me[H_PEL] = img->lambda_me[5][img->masterQP][H_PEL];
-      enc_mb->lambda_me[Q_PEL] = img->lambda_me[5][img->masterQP][Q_PEL];
-
-      enc_mb->lambda_mf[F_PEL] = img->lambda_mf[5][img->masterQP][F_PEL];
-      enc_mb->lambda_mf[H_PEL] = img->lambda_mf[5][img->masterQP][H_PEL];
-      enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[5][img->masterQP][Q_PEL];
-    }
-    else
-    {
-      enc_mb->lambda_md = img->lambda_md[img->type][img->masterQP];
-      enc_mb->lambda_me[F_PEL] = img->lambda_me[img->type][img->masterQP][F_PEL];
-      enc_mb->lambda_me[H_PEL] = img->lambda_me[img->type][img->masterQP][H_PEL];
-      enc_mb->lambda_me[Q_PEL] = img->lambda_me[img->type][img->masterQP][Q_PEL];
-
-      enc_mb->lambda_mf[F_PEL] = img->lambda_mf[img->type][img->masterQP][F_PEL];
-      enc_mb->lambda_mf[H_PEL] = img->lambda_mf[img->type][img->masterQP][H_PEL];
-      enc_mb->lambda_mf[Q_PEL] = img->lambda_mf[img->type][img->masterQP][Q_PEL];
-    }
-  }
-
-  // Initialize bipredME decisions
-  for (mode=0; mode<MAXMODE; mode++)
-  {
-    img->bi_pred_me[mode]=0;
-  }
-
+ 
   if (!img->MbaffFrameFlag)
   {
     for (l = LIST_0; l < BI_PRED; l++)
@@ -232,11 +197,11 @@ void init_enc_mb_params(Macroblock* currMB, RD_PARAMS *enc_mb, int intra, int bs
 *    computation of prediction list (including biprediction) cost
 *************************************************************************************
 */
-void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_PARAMS enc_mb, int bmcost[5], char best_ref[2])
+void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_PARAMS *enc_mb, int bmcost[5], char best_ref[2])
 {
   short ref;
   int mcost;
-  int cur_list = list < BI_PRED ? enc_mb.list_offset[list] : enc_mb.list_offset[LIST_0];
+  int cur_list = list < BI_PRED ? enc_mb->list_offset[list] : enc_mb->list_offset[LIST_0];
 
   //--- get cost and reference frame for forward prediction ---
 
@@ -252,8 +217,8 @@ void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_
           ((params->sp2_frame_indicator || params->sp_output_indicator) && ((img->type == P_SLICE || img->type == SP_SLICE) &&(ref==0))))
         {
           mcost  = (params->rdopt
-            ? REF_COST (enc_mb.lambda_mf[Q_PEL], ref, cur_list)
-            : (int) (2 * enc_mb.lambda_me[Q_PEL] * imin(ref, 1)));
+            ? REF_COST (enc_mb->lambda_mf[Q_PEL], ref, cur_list)
+            : (int) (2 * enc_mb->lambda_me[Q_PEL] * imin(ref, 1)));
 
           mcost += motion_cost[mode][list][ref][block];
           if (mcost < bmcost[list])
@@ -278,34 +243,34 @@ void list_prediction_cost(Macroblock *currMB, int list, int block, int mode, RD_
       else
       {
         bmcost[list]  = (params->rdopt
-          ? (REF_COST  (enc_mb.lambda_mf[Q_PEL], (short)best_ref[LIST_0], cur_list)
-          +  REF_COST  (enc_mb.lambda_mf[Q_PEL], (short)best_ref[LIST_1], cur_list + LIST_1))
-          : (int) (2 * (enc_mb.lambda_me[Q_PEL] * (imin((short)best_ref[LIST_0], 1) + imin((short)best_ref[LIST_1], 1)))));
-        bmcost[list] += BIDPartitionCost (currMB, mode, block, best_ref, enc_mb.lambda_mf[Q_PEL]);
+          ? (REF_COST  (enc_mb->lambda_mf[Q_PEL], (short)best_ref[LIST_0], cur_list)
+          +  REF_COST  (enc_mb->lambda_mf[Q_PEL], (short)best_ref[LIST_1], cur_list + LIST_1))
+          : (int) (2 * (enc_mb->lambda_me[Q_PEL] * (imin((short)best_ref[LIST_0], 1) + imin((short)best_ref[LIST_1], 1)))));
+        bmcost[list] += BIDPartitionCost (currMB, mode, block, best_ref, enc_mb->lambda_mf[Q_PEL]);
       }
     }
     else
     {
       bmcost[list]  = (params->rdopt
-        ? (REF_COST  (enc_mb.lambda_mf[Q_PEL], (short)best_ref[LIST_0], cur_list)
-        +  REF_COST  (enc_mb.lambda_mf[Q_PEL], (short)best_ref[LIST_1], cur_list + LIST_1))
-        : (int) (2 * (enc_mb.lambda_me[Q_PEL] * (imin((short)best_ref[LIST_0], 1) + imin((short)best_ref[LIST_1], 1)))));
-      bmcost[list] += BIDPartitionCost (currMB, mode, block, best_ref, enc_mb.lambda_mf[Q_PEL]);
+        ? (REF_COST  (enc_mb->lambda_mf[Q_PEL], (short)best_ref[LIST_0], cur_list)
+        +  REF_COST  (enc_mb->lambda_mf[Q_PEL], (short)best_ref[LIST_1], cur_list + LIST_1))
+        : (int) (2 * (enc_mb->lambda_me[Q_PEL] * (imin((short)best_ref[LIST_0], 1) + imin((short)best_ref[LIST_1], 1)))));
+      bmcost[list] += BIDPartitionCost (currMB, mode, block, best_ref, enc_mb->lambda_mf[Q_PEL]);
     }
   }
   else
   {
     bmcost[list]  = (params->rdopt
-      ? (REF_COST (enc_mb.lambda_mf[Q_PEL], 0, cur_list)
-      +  REF_COST (enc_mb.lambda_mf[Q_PEL], 0, cur_list + LIST_1))
-      : (int) (4 * enc_mb.lambda_me[Q_PEL]));
-    bmcost[list] += BPredPartitionCost(currMB, mode, block, 0, 0, enc_mb.lambda_mf[Q_PEL], !(list&1));
+      ? (REF_COST (enc_mb->lambda_mf[Q_PEL], 0, cur_list)
+      +  REF_COST (enc_mb->lambda_mf[Q_PEL], 0, cur_list + LIST_1))
+      : (int) (4 * enc_mb->lambda_me[Q_PEL]));
+    bmcost[list] += BPredPartitionCost(currMB, mode, block, 0, 0, enc_mb->lambda_mf[Q_PEL], !(list&1));
   }
 }
 
-int compute_ref_cost(RD_PARAMS enc_mb, int ref, int list)
+int compute_ref_cost(RD_PARAMS *enc_mb, int ref, int list)
 {
-  return WEIGHTED_COST(enc_mb.lambda_mf[Q_PEL],((listXsize[enc_mb.list_offset[list]] <= 1)? 0:refbits[ref]));
+  return WEIGHTED_COST(enc_mb->lambda_mf[Q_PEL],((listXsize[enc_mb->list_offset[list]] <= 1)? 0:refbits[ref]));
 }
 
 /*!
@@ -314,82 +279,23 @@ int compute_ref_cost(RD_PARAMS enc_mb, int ref, int list)
 *    Determination of prediction list based on simple distortion computation
 *************************************************************************************
 */
-void determine_prediction_list(int mode, int bmcost[5], char best_ref[2], char *best_pdir, int *cost, short *bi_pred_me)
+void determine_prediction_list(int mode, int bmcost[5], char best_ref[2], char *best_pdir, int *cost, short *bipred_me)
 {
-  if ((!params->BiPredMotionEstimation) || (mode != 1))
+  int bestlist;  
+  
+  *cost += iminarray ( bmcost, 5, &bestlist);
+  
+  if (bestlist <= BI_PRED)  //LIST_0, LIST_1 & BI_DIR
   {
-    //--- get prediction direction ----
-    if  (bmcost[LIST_0] <= bmcost[LIST_1]
-      && bmcost[LIST_0] <= bmcost[BI_PRED])
-    {
-      *best_pdir = 0;
-      *cost += bmcost[LIST_0];
-    }
-    else if (bmcost[LIST_1] <= bmcost[LIST_0]
-      &&     bmcost[LIST_1] <= bmcost[BI_PRED])
-    {
-      *best_pdir = 1;
-      *cost += bmcost[LIST_1];
-    }
-    else
-    {
-      *best_pdir = 2;
-      *cost += bmcost[BI_PRED];
-    }
+    *best_pdir = bestlist; 
+    *bipred_me = 0;
   }
-  else
+  else                      //BI_PRED_L0 & BI_PRED_L1
   {
-    img->bi_pred_me[mode]=0;
-    *bi_pred_me = 0;
-    //--- get prediction direction ----
-    if  (bmcost[LIST_0] <= bmcost[LIST_1]
-      && bmcost[LIST_0] <= bmcost[BI_PRED]
-      && bmcost[LIST_0] <= bmcost[BI_PRED_L0]
-      && bmcost[LIST_0] <= bmcost[BI_PRED_L1])
-    {
-      *best_pdir = 0;
-      *cost += bmcost[LIST_0];
-      //best_ref[LIST_1] = 0;
-    }
-    else if (bmcost[LIST_1] <= bmcost[LIST_0]
-      &&     bmcost[LIST_1] <= bmcost[BI_PRED]
-      &&     bmcost[LIST_1] <= bmcost[BI_PRED_L0]
-      &&     bmcost[LIST_1] <= bmcost[BI_PRED_L1])
-    {
-      *best_pdir = 1;
-      *cost += bmcost[LIST_1];
-      //best_ref[LIST_0] = 0;
-    }
-    else if (bmcost[BI_PRED] <= bmcost[LIST_0]
-      &&     bmcost[BI_PRED] <= bmcost[LIST_1]
-      &&     bmcost[BI_PRED] <= bmcost[BI_PRED_L0]
-      &&     bmcost[BI_PRED] <= bmcost[BI_PRED_L1])
-    {
-      *best_pdir = 2;
-      *cost += bmcost[BI_PRED];
-      //best_ref[LIST_1] = 0;
-    }
-    else if (bmcost[BI_PRED_L0] <= bmcost[LIST_0]
-      &&     bmcost[BI_PRED_L0] <= bmcost[LIST_1]
-      &&     bmcost[BI_PRED_L0] <= bmcost[BI_PRED]
-      &&     bmcost[BI_PRED_L0] <= bmcost[BI_PRED_L1])
-    {
-      *best_pdir = 2;
-      *cost += bmcost[BI_PRED_L0];
-      *bi_pred_me = 1;
-      img->bi_pred_me[mode]=1;
-      best_ref[LIST_1] = 0;
-      best_ref[LIST_0] = 0;
-    }
-    else
-    {
-      *best_pdir = 2;
-      *cost += bmcost[BI_PRED_L1];
-      *bi_pred_me = 2;
-      best_ref[LIST_1] = 0;
-      best_ref[LIST_0] = 0;
-      img->bi_pred_me[mode]=2;
-    }
+    *best_pdir = 2;    
+    *bipred_me = bestlist - 2;
+    best_ref[LIST_1] = 0;
+    best_ref[LIST_0] = 0;
   }
 }
 
@@ -401,7 +307,7 @@ void determine_prediction_list(int mode, int bmcost[5], char best_ref[2], char *
 */
 void compute_mode_RD_cost(int mode,
                           Macroblock *currMB,
-                          RD_PARAMS enc_mb,
+                          RD_PARAMS *enc_mb,
                           double *min_rdcost,
                           double *min_dcost,
                           double *min_rate,
@@ -413,7 +319,7 @@ void compute_mode_RD_cost(int mode,
   currMB->luma_transform_size_8x8_flag = params->Transform8x8Mode==2
     ?  (mode >= 1 && mode <= 3)
     || (mode == 0 && bslice && active_sps->direct_8x8_inference_flag)
-    || ((mode == P8x8) && (enc_mb.valid[4]))
+    || ((mode == P8x8) && (enc_mb->valid[4]))
     :  0;
   //store_coding_state (currMB, cs_cm); // RD
   SetModesAndRefframeForBlocks (currMB, mode);
@@ -426,13 +332,13 @@ void compute_mode_RD_cost(int mode,
   {
     while(1)
     {
-      if (RDCost_for_macroblocks (currMB, enc_mb.lambda_md, mode, min_rdcost, min_dcost, min_rate, i16mode))
+      if (RDCost_for_macroblocks (currMB, enc_mb->lambda_md, mode, min_rdcost, min_dcost, min_rate, i16mode))
       {
         //Rate control
         if (params->RCEnable)
         {
           if(mode == P8x8)
-            rc_store_diff(img->opix_x,img->opix_y, currMB->luma_transform_size_8x8_flag == 1 ? tr8x8.mpr8x8 : tr4x4.mpr8x8);
+            rc_store_diff(img->opix_x, img->opix_y, currMB->luma_transform_size_8x8_flag == 1 ? tr8x8.mpr8x8 : tr4x4.mpr8x8);
           else
             rc_store_diff(img->opix_x, img->opix_y, pred);
         }
@@ -468,7 +374,7 @@ void compute_mode_RD_cost(int mode,
           continue;
         }
         //=========== try mb_type P8x8 for mode 4 with 4x4/8x8 transform ===========
-        else if ((mode == P8x8) && (enc_mb.valid[4]) && (currMB->luma_transform_size_8x8_flag == 0))
+        else if ((mode == P8x8) && (enc_mb->valid[4]) && (currMB->luma_transform_size_8x8_flag == 0))
         {
           currMB->luma_transform_size_8x8_flag = 1; //check 8x8 partition for transform size 8x8
           continue;
@@ -484,14 +390,14 @@ void compute_mode_RD_cost(int mode,
     }
 
     // Encode with no coefficients. Currently only for direct. This could be extended to all other modes as in example.
-    //if (mode < P8x8 && (*inter_skip == 0) && enc_mb.valid[mode] && currMB->cbp && (currMB->cbp&15) != 15 && !params->nobskip)
-    if ( bslice && mode == 0 && (*inter_skip == 0) && enc_mb.valid[mode] 
+    //if (mode < P8x8 && (*inter_skip == 0) && enc_mb->valid[mode] && currMB->cbp && (currMB->cbp&15) != 15 && !params->nobskip)
+    if ( bslice && mode == 0 && (*inter_skip == 0) && enc_mb->valid[mode] 
     && currMB->cbp && (currMB->cbp&15) != 15 && !params->nobskip
     && !(currMB->qp_scaled[0] == 0 && img->lossless_qpprime_flag==1) )
     {
       img->NoResidueDirect = 1;
 
-      if (RDCost_for_macroblocks (currMB, enc_mb.lambda_md, mode, min_rdcost, min_dcost, min_rate, i16mode))
+      if (RDCost_for_macroblocks (currMB, enc_mb->lambda_md, mode, min_rdcost, min_dcost, min_rate, i16mode))
       {
         //Rate control
         if (params->RCEnable)
@@ -510,7 +416,7 @@ void compute_mode_RD_cost(int mode,
 *    Mode Decision for an 8x8 sub-macroblock
 *************************************************************************************
 */
-void submacroblock_mode_decision(RD_PARAMS enc_mb,
+void submacroblock_mode_decision(RD_PARAMS *enc_mb,
                                  RD_8x8DATA *dataTr,
                                  Macroblock *currMB,
                                  int ***cofACtr,
@@ -544,12 +450,13 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
     ? (transform8x8 ? img->fadjust8x8Cr : img->fadjust4x4Cr): NULL;
   int lumaAdjustIndex   = transform8x8 ? 2 : 3;
   int chromaAdjustIndex = transform8x8 ? 0 : 2;
-  short pdir;
-  short bi_pred_me;
+  short pdir, bipred_me = 0;
+
 
   char best_pdir = 0;
   char best_ref[2] = {0, -1};
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
+
 #ifdef BEST_NZ_COEFF
   int best_nz_coeff[2][2];
 #endif
@@ -575,11 +482,11 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
   store_coding_state (currMB, cs_cm);
 
   //=====  LOOP OVER POSSIBLE CODING MODES FOR 8x8 SUB-PARTITION  =====
-  for (min_cost8x8 = INT_MAX, min_rdcost = 1e30, index = (bslice?0:1); index < maxindex; index++)
+  for (min_cost8x8 = INT_MAX, min_rdcost = 1e20, index = (bslice?0:1); index < maxindex; index++)
   {
     mode = b8_mode_table[index];
     *cost = 0;
-    if (enc_mb.valid[mode] && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
+    if (enc_mb->valid[mode] && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
     {
       curr_cbp_blk = 0;
 
@@ -611,7 +518,7 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
             switch(params->Transform8x8Mode)
             {
             case 1: // Mixture of 8x8 & 4x4 transform
-              if((direct8x8_tmp < direct4x4_tmp) || !(enc_mb.valid[5] && enc_mb.valid[6] && enc_mb.valid[7]))
+              if((direct8x8_tmp < direct4x4_tmp) || !(enc_mb->valid[5] && enc_mb->valid[6] && enc_mb->valid[7]))
                 *cost = direct8x8_tmp;
               else
                 *cost = direct4x4_tmp;
@@ -644,7 +551,7 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
         char b_ref;
         //======= motion estimation for all reference frames ========
         //-----------------------------------------------------------
-        memcpy(lambda_mf, enc_mb.lambda_mf, 3 * sizeof(int));
+        memcpy(lambda_mf, enc_mb->lambda_mf, 3 * sizeof(int));
         if (params->CtxAdptLagrangeMult == 1)
         {
           lambda_mf[F_PEL] = (int)(lambda_mf[F_PEL] * lambda_mf_factor);
@@ -662,22 +569,21 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
         block_x = img->block_x + (block & 0x01)*2;
         block_y = img->block_y + (block & 0x02);
         b_ref = best_ref[LIST_0];
-        ref_pic_num = enc_picture->ref_pic_num[enc_mb.list_offset[LIST_0]][(short) b_ref];
+        ref_pic_num = enc_picture->ref_pic_num[enc_mb->list_offset[LIST_0]][(short) b_ref];
 
         for (j = block_y; j< block_y + 2; j++)
         {
-          memset(&enc_picture->ref_idx [LIST_0][j][block_x], b_ref, 2 * sizeof(char));
+          memset(&enc_picture->motion.ref_idx [LIST_0][j][block_x], b_ref, 2 * sizeof(char));
         }
 
         for (j = block_y; j< block_y + 2; j++)
         {
           for (i = block_x; i < block_x + 2; i++)
           {
-            enc_picture->ref_pic_id[LIST_0][j][i] = ref_pic_num;
+            enc_picture->motion.ref_pic_id[LIST_0][j][i] = ref_pic_num;
           }
         }
 
-
         if (bslice)
         {
           //--- get cost and reference frame for LIST 1 prediction ---
@@ -687,16 +593,28 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
 
           // Compute bipredictive cost between best list 0 and best list 1 references
           list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);
+          
+          // currently Bi prediction ME is only supported for modes 1, 2, 3 and only for ref 0 and only for ref 0
+          if (is_bipred_enabled(mode))
+          {
+            list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
+            list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
+          }
+          else
+          {
+            bmcost[BI_PRED_L0] = INT_MAX;
+            bmcost[BI_PRED_L1] = INT_MAX;
+          }
 
           //--- get prediction direction ----
-          determine_prediction_list(mode, bmcost, best_ref, &best_pdir, cost, &bi_pred_me);
-
+          determine_prediction_list(mode, bmcost, best_ref, &best_pdir, cost, &bipred_me);
+        
           //store backward reference index for every block
           for (k = LIST_0; k <= LIST_1; k++)
           {
             for (j = block_y; j< block_y + 2; j++)
             {
-              memset(&enc_picture->ref_idx[k][j][block_x], best_ref[k], 2 * sizeof(char));
+              memset(&enc_picture->motion.ref_idx[k][j][block_x], best_ref[k], 2 * sizeof(char));
             }
           }
         } // if (bslice)
@@ -710,25 +628,26 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
       if (params->rdopt)
       {
         //--- get and check rate-distortion cost ---
-        rdcost = RDCost_for_8x8blocks (currMB, &cnt_nonz, &curr_cbp_blk, enc_mb.lambda_md,
-          block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1]);
+        rdcost = RDCost_for_8x8blocks (currMB, &cnt_nonz, &curr_cbp_blk, enc_mb->lambda_md,
+          block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me);
       }
       else
       {
         if (*cost!=INT_MAX)
-          *cost += (REF_COST (enc_mb.lambda_mf[Q_PEL], B8Mode2Value (mode, best_pdir),
-          enc_mb.list_offset[(best_pdir < 1 ? LIST_0 : LIST_1)]) - 1);
+          *cost += (REF_COST (enc_mb->lambda_mf[Q_PEL], B8Mode2Value (mode, best_pdir),
+          enc_mb->list_offset[(best_pdir < 1 ? LIST_0 : LIST_1)]) - 1);
       }
 
       //--- set variables if best mode has changed ---
       if ( ( params->rdopt && rdcost < min_rdcost) || (!params->rdopt && *cost < min_cost8x8))
       {
-        min_cost8x8                 = *cost;
-        min_rdcost                  = rdcost;
-        dataTr->part8x8mode [block] = mode;
-        dataTr->part8x8pdir [block] = best_pdir;
-        dataTr->part8x8l0ref[block] = best_ref[LIST_0];
-        dataTr->part8x8l1ref[block] = best_ref[LIST_1];
+        min_cost8x8                  = *cost;
+        min_rdcost                   = rdcost;
+        dataTr->part8x8mode  [block] = mode;
+        dataTr->part8x8pdir  [block] = best_pdir;
+        dataTr->part8x8l0ref [block] = best_ref[LIST_0];
+        dataTr->part8x8l1ref [block] = best_ref[LIST_1];
+        dataTr->part8x8bipred[block] = bipred_me;
 
         currMB->b8mode[block] = mode;
 
@@ -774,7 +693,12 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
           for (j=j0; j<j0 + BLOCK_SIZE_8x8; j++)
           {
             memcpy(&dataTr->rec_mbY8x8[j][i0],&enc_picture->imgY[img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
-            memcpy(&dataTr->mpr8x8[j][i0],&curr_mpr[j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
+            memcpy(&dataTr->mpr8x8[j][i0],&mb_pred[j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
+          }
+
+          if (params->rdopt == 3)
+          {
+            errdo_store_best_block(img, decs->dec_mbY8x8, enc_picture->p_dec_img[0], i0, j0, BLOCK_SIZE_8x8);  //Store best 8x8 block for each hypothetical decoder
           }
 
           if(img->type==SP_SLICE && (!si_frame_indicator))
@@ -784,14 +708,15 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
               memcpy(&dataTr->lrec[j][i0],&lrec[img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(int));
             }
           }
+ 
           if(img->P444_joined) 
           {
             for (j=j0; j<j0+8; j++)    
             {
               memcpy(&dataTr->rec_mb8x8_cr[0][j][i0],&enc_picture->imgUV[0][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
               memcpy(&dataTr->rec_mb8x8_cr[1][j][i0],&enc_picture->imgUV[1][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
-              memcpy(&dataTr->mpr8x8CbCr[0][j][i0],&img->mpr[1][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
-              memcpy(&dataTr->mpr8x8CbCr[1][j][i0],&img->mpr[2][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
+              memcpy(&dataTr->mpr8x8CbCr[0][j][i0],&img->mb_pred[1][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
+              memcpy(&dataTr->mpr8x8CbCr[1][j][i0],&img->mb_pred[2][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
             }
           }
           
@@ -823,7 +748,7 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
 
       //--- re-set coding state as it was before coding with current mode was performed ---
       reset_coding_state (currMB, cs_cm);
-    } // if ((enc_mb.valid[mode] && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
+    } // if ((enc_mb->valid[mode] && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
   } // for (min_rdcost=1e30, index=(bslice?0:1); index<6; index++)
 
 #ifdef BEST_NZ_COEFF
@@ -835,13 +760,13 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
 #endif
 
   if (!transform8x8)
-    dataTr->cost8x8 += min_cost8x8;
+    dataTr->mb_p8x8_cost += min_cost8x8;
 
   if (!params->rdopt)
   {
     if (transform8x8)
     {
-      dataTr->cost8x8 += min_cost8x8;
+      dataTr->mb_p8x8_cost += min_cost8x8;
       mode = dataTr->part8x8mode[block];
       pdir = dataTr->part8x8pdir[block];
     }
@@ -852,8 +777,10 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
     }
 
     curr_cbp_blk  = 0;
+    currMB->bipred_me[block] = dataTr->part8x8bipred[block];
     best_cnt_nonz = LumaResidualCoding8x8 (currMB, &dummy, &curr_cbp_blk, block, pdir,
-      (pdir==0||pdir==2?mode:0), (pdir==1||pdir==2?mode:0), dataTr->part8x8l0ref[block], dataTr->part8x8l1ref[block]);
+      (pdir == 0 || pdir == 2 ? mode : 0), (pdir == 1 || pdir == 2 ? mode : 0), 
+      dataTr->part8x8l0ref[block], dataTr->part8x8l1ref[block]);
 
     if (img->P444_joined)
       best_cnt_nonz += coeff_cost_cr[1] + coeff_cost_cr[2];
@@ -879,7 +806,7 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
     }
     for (j = j0; j < j0 + BLOCK_SIZE_8x8; j++)
     {
-      memcpy(&dataTr->mpr8x8[j][i0], &curr_mpr[j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
+      memcpy(&dataTr->mpr8x8[j][i0], &mb_pred[j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
     }
 
 
@@ -897,8 +824,8 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
       {   
         memcpy(&dataTr->rec_mb8x8_cr[0][j][i0], &enc_picture->imgUV[0][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
         memcpy(&dataTr->rec_mb8x8_cr[1][j][i0], &enc_picture->imgUV[1][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
-        memcpy(&dataTr->mpr8x8CbCr[0][j][i0], &img->mpr[1][j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel)); 
-        memcpy(&dataTr->mpr8x8CbCr[1][j][i0], &img->mpr[2][j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
+        memcpy(&dataTr->mpr8x8CbCr[0][j][i0], &img->mb_pred[1][j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel)); 
+        memcpy(&dataTr->mpr8x8CbCr[1][j][i0], &img->mb_pred[2][j][i0], BLOCK_SIZE_8x8 * sizeof (imgpel));
       }
     }   
   }
@@ -921,6 +848,12 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
       {
         memcpy(&enc_picture->imgY[img->pix_y + j][img->pix_x], dataTr->rec_mbY8x8[j], BLOCK_SIZE_8x8 * sizeof(imgpel));
       }
+
+      if (params->rdopt == 3)
+      {
+        errdo_get_best_block(img, enc_picture->p_dec_img[0], decs->dec_mbY8x8, j0, BLOCK_SIZE_8x8);
+      }
+
       if(img->type==SP_SLICE &&(!si_frame_indicator))
       {
         for (j = j0; j < j0 + BLOCK_SIZE_8x8; j++)
@@ -947,7 +880,7 @@ void submacroblock_mode_decision(RD_PARAMS enc_mb,
     StoreNewMotionVectorsBlock8x8(0, block, dataTr->part8x8mode[block], dataTr->part8x8l0ref[block], dataTr->part8x8l1ref[block], dataTr->part8x8pdir[block], bslice);
   }
   //===== set motion vectors and reference frames (prediction) =====
-  SetRefAndMotionVectors (currMB, block, dataTr->part8x8mode[block], dataTr->part8x8pdir[block], dataTr->part8x8l0ref[block], dataTr->part8x8l1ref[block]);
+  SetRefAndMotionVectors (currMB, block, dataTr->part8x8mode[block], dataTr->part8x8pdir[block], dataTr->part8x8l0ref[block], dataTr->part8x8l1ref[block], dataTr->part8x8bipred[block]);
 
   //===== set the coding state after current block =====
   //if (transform8x8 == 0 || block < 3)
@@ -1037,4 +970,99 @@ void update_lambda_costs(RD_PARAMS *enc_mb, int lambda_mf[3])
   }
 }
 
+/*!
+ *************************************************************************************
+ * \brief
+ *    Return array's minimum and its index
+ *************************************************************************************
+ */
+int iminarray ( int arr[], int size, int *minind )
+{
+  int i; 
+  int mincand = arr[0];
+  *minind = 0;
+  for ( i = 1; i < size; i++ )
+  {
+    if (arr[i] < mincand)
+    {
+      mincand = arr[i];
+      *minind = i;
+    }
+  }
+  return mincand;
+} 
 
+/*!
+ *************************************************************************************
+ * \brief
+ *    Determines whether bi prediction is enabaled for current mode
+ *************************************************************************************
+ */
+int is_bipred_enabled(int mode) 
+{
+  int enabled = 0;
+  mode = mode == P8x8 ? 4: mode;
+  if (params->BiPredMotionEstimation)
+  {
+    if (mode > 0 && mode < 5)
+    {
+      enabled = (params->BiPredSearch[mode - 1]) ? 1: 0;
+    }    
+    else
+    {
+      enabled = 0;
+    }
+  }
+  else
+  {
+    enabled = 0;
+  }
+  return enabled;
+}
+
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Update prediction direction for mode P16x16 to check all prediction directions
+ *************************************************************************************
+ */
+void update_prediction_for_mode16x16(Block8x8Info *b8x8info, int ctr16x16, int *index)
+{
+  char pdir = 0;
+  short i, bipred_me = 0;
+  switch (ctr16x16)
+  {
+    case 0:
+      *index = *index - 1;
+      break;
+    case 1:
+      pdir = 1;
+      *index = *index - 1;
+      break;
+    case 2:
+      pdir = 2;
+      if (params->BiPredMotionEstimation)
+      {
+        *index = *index - 1;
+      }
+      break;
+    case 3:
+      pdir = 2;
+      bipred_me = 1;
+      *index = *index - 1;
+      break;
+    case 4:
+      pdir = 2;
+      bipred_me = 2;
+      break;
+    default:
+      error("invalid 'ctr16x16' value", -1);
+      break;
+  }
+  for (i = 0; i< 4; i++)
+  {
+    b8x8info->bipred8x8me[1][i] = bipred_me;
+    b8x8info->best8x8pdir[1][i] = pdir;
+  }
+}
diff --git a/lencod/src/mv-search.c b/lencod/src/mv-search.c
index 4e6eade..d723ea6 100644
--- a/lencod/src/mv-search.c
+++ b/lencod/src/mv-search.c
@@ -70,7 +70,7 @@ int (*IntPelME)       (Macroblock *, imgpel *, short, int, int, char ***, short
                        int, int, int, short[2], short[2], int, int, int, int);
 
 int (*BiPredME)       (Macroblock *, imgpel *, short, int, int, char  ***, short  ****,
-                       int, int, int, short[2], short[2], short[2], short[2], int, int, int, int);
+                       int, int, int, short[2], short[2], short[2], short[2], int, int, int, int, int);
 
 int (*SubPelBiPredME) (imgpel* orig_pic, short ref, int list, int pic_pix_x, int pic_pix_y,
                        int blocktype, short pred_mv1[2], short pred_mv2[2], short mv1[2], short mv2[2], 
@@ -80,6 +80,10 @@ int (*SubPelME)       (imgpel* orig_pic, short ref, int list, int list_offset, i
                        int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);
 
 
+int BlockMotionSearch (Macroblock *currMB, short,int,int,int,int,int, int*);
+int BiPredBlockMotionSearch(Macroblock *currMB, short[2], short*, short, int, int, int, int , int, int, int*);
+
+int GetSkipCostMB     (Macroblock *currMB);
 
 extern ColocatedParams *Co_located;
 extern const short block_type_shift_factor[8];
@@ -246,18 +250,18 @@ void SetMotionVectorPredictor (Macroblock *currMB,
   {
     if (mb_x < 8)  // first column of 8x8 blocks
     {
-      if (mb_y==8)
+      if (mb_y == 8 )
       {
         if (blockshape_x == 16)      block_c.available  = 0;
       }
-      else
+      else if (mb_x+blockshape_x == 8)
       {
-        if (mb_x+blockshape_x == 8)  block_c.available = 0;
+          block_c.available = 0;
       }
     }
-    else
+    else if (mb_x+blockshape_x == 16)
     {
-      if (mb_x+blockshape_x == 16)   block_c.available = 0;
+      block_c.available = 0;
     }
   }
 
@@ -311,9 +315,12 @@ void SetMotionVectorPredictor (Macroblock *currMB,
   /* Prediction if only one of the neighbors uses the reference frame
   *  we are checking
   */
-  if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       mvPredType = MVPRED_L;
-  else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  mvPredType = MVPRED_U;
-  else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  mvPredType = MVPRED_UR;
+  if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       
+    mvPredType = MVPRED_L;
+  else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  
+    mvPredType = MVPRED_U;
+  else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  
+    mvPredType = MVPRED_UR;
   // Directional predictions
   if(blockshape_x == 8 && blockshape_y == 16)
   {
@@ -419,8 +426,7 @@ void SetMotionVectorPredictor (Macroblock *currMB,
 *    Initialize the motion search
 ************************************************************************
 */
-void
-Init_Motion_Search_Module ()
+void Init_Motion_Search_Module (void)
 {
   int bits, i_min, i_max, k;
   int i, l;
@@ -567,10 +573,12 @@ Init_Motion_Search_Module ()
       InitializeFastFullIntegerSearch ();
 
     init_ME_engine(params->SearchMode);
+
+    if (params->SearchMode == UM_HEX)
+      UMHEX_DefineThreshold();
   }
 }
 
-
 /*!
  ************************************************************************
  * \brief
@@ -600,6 +608,20 @@ Clear_Motion_Search_Module ()
     ClearFastFullIntegerSearch ();
 }
 
+static inline int mv_bits_cost(short ***all_mv, short ***p_mv, int by, int bx, int step_v0, int step_v, int step_h0, int step_h, int mvd_bits)
+{
+  int v, h;
+  for (v=by; v<by + step_v0; v+=step_v)
+  {
+    for (h=bx; h<bx + step_h0; h+=step_h)
+    {
+      mvd_bits += mvbits[ all_mv[v][h][0] - p_mv[v][h][0] ];
+      mvd_bits += mvbits[ all_mv[v][h][1] - p_mv[v][h][1] ];
+    }
+  }
+  return mvd_bits;
+}
+
 /*!
  ***********************************************************************
  * \brief
@@ -633,29 +655,16 @@ int BPredPartitionCost (Macroblock *currMB,
   int   by0_part = by0[parttype][block8x8];
   int   bx0_part = bx0[parttype][block8x8];
 
-  short   ***all_mv_l0 = list ? img->bipred_mv1[LIST_0][ref_l0][blocktype] : img->bipred_mv2[LIST_0][ref_l0][blocktype];
-  short   ***all_mv_l1 = list ? img->bipred_mv1[LIST_1][ref_l1][blocktype] : img->bipred_mv2[LIST_1][ref_l1][blocktype];
+  short   ***all_mv_l0 = img->bipred_mv[list][LIST_0][ref_l0][blocktype]; 
+  short   ***all_mv_l1 = img->bipred_mv[list][LIST_1][ref_l1][blocktype]; 
   short   ***p_mv_l0 = img->pred_mv[LIST_0][ref_l0][blocktype];
   short   ***p_mv_l1 = img->pred_mv[LIST_1][ref_l1][blocktype];
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
-  for (v = by0_part; v < by0_part + step_v0; v += step_v)
-  {
-    for (h = bx0_part; h < bx0_part + step_h0; h += step_h)
-    {
-      mvd_bits += mvbits[ all_mv_l0[v][h][0] - p_mv_l0[v][h][0] ];
-      mvd_bits += mvbits[ all_mv_l0[v][h][1] - p_mv_l0[v][h][1] ];
-    }
-  }
-
-  for (v = by0_part; v < by0_part + step_v0; v += step_v)
-  {
-    for (h = bx0_part; h < bx0_part + step_h0; h += step_h)
-    {
-      mvd_bits += mvbits[ all_mv_l1[v][h][0] - p_mv_l1[v][h][0] ];
-      mvd_bits += mvbits[ all_mv_l1[v][h][1] - p_mv_l1[v][h][1] ];
-    }
-  }
+  // List0 
+  mvd_bits = mv_bits_cost(all_mv_l0, p_mv_l0, by0_part, bx0_part, step_v0, step_v, step_h0, step_h, mvd_bits);
+  // List1
+  mvd_bits = mv_bits_cost(all_mv_l1, p_mv_l1, by0_part, bx0_part, step_v0, step_v, step_h0, step_h, mvd_bits);
 
   mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
 
@@ -673,7 +682,7 @@ int BPredPartitionCost (Macroblock *currMB,
       {
         for (i = 0; i < 4; i++)
           diff64[k++] = curr_blk[byy+j][bxx+i] =
-          pCurImg[pic_pix_y+j][pic_pix_x+i] - curr_mpr[j+block_y][i+block_x];
+          pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
       }
 
       if ((!params->Transform8x8Mode) || (blocktype>4))
@@ -767,12 +776,12 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
   if ( ChromaMEEnable )
   {
     // copy the original cmp1 and cmp2 data to the orig_pic matrix
-    for ( i = 0; i<=1; i++)
+    for ( i = 1; i<=2; i++)
     {
-      orig_pic_tmp = orig_pic + (256 << i);
+      orig_pic_tmp = orig_pic + (256 << (i - 1));
       for (j = pic_pix_y_c; j < pic_pix_y_c + bsy_c; j++)
       {
-        memcpy(orig_pic_tmp, &(imgUV_org[i][j][pic_pix_x_c]), bsx_c * sizeof(imgpel));
+        memcpy(orig_pic_tmp, &(pImgOrg[i][j][pic_pix_x_c]), bsx_c * sizeof(imgpel));
         orig_pic_tmp += bsx_c;
       }
     }
@@ -796,9 +805,10 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
   //===========================================
 
   if (params->SearchMode == UM_HEX)
-    UMHEXSetMotionVectorPredictor(currMB, pred_mv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, mb_x, mb_y, bsx, bsy, &search_range);
+    UMHEXSetMotionVectorPredictor(currMB, pred_mv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, mb_x, mb_y, bsx, bsy, &search_range);
   else
-    SetMotionVectorPredictor (currMB, pred_mv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, mb_x, mb_y, bsx, bsy);
+    SetMotionVectorPredictor (currMB, pred_mv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, mb_x, mb_y, bsx, bsy);
+
 
   //==================================
   //=====   INTEGER-PEL SEARCH   =====
@@ -825,8 +835,8 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
   clip_mv_range(img, search_range, mv, params->EPZSGrid);
 
   //--- perform motion search ---
-  min_mcost = IntPelME (currMB, orig_pic, ref, list, list_offset,
-    enc_picture->ref_idx, enc_picture->mv, pic_pix_x, pic_pix_y, blocktype,
+    min_mcost = IntPelME (currMB, orig_pic, ref, list, list_offset,
+    enc_picture->motion.ref_idx, enc_picture->motion.mv, pic_pix_x, pic_pix_y, blocktype,
     pred_mv, mv, search_range<<(params->EPZSGrid), min_mcost, lambda_factor[F_PEL], apply_weights);
 
   //===== convert search center to quarter-pel units =====
@@ -892,25 +902,65 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
   }
 
 
-  // Bipred ME consideration. This needs to go in a separate function, and at some point support smaller partitions
-  if (img->type==B_SLICE && params->BiPredMotionEstimation != 0 && (blocktype == 1) && (ref==0))
+  // Bipred ME consideration: returns minimum bipred cost
+  if (img->type == B_SLICE && is_bipred_enabled(blocktype) && (ref == 0)) 
   {
-    short   ******bipred_mv = list ? img->bipred_mv1 : img->bipred_mv2;
-    int     min_mcostbi = max_value;
-    short   bimv[2] = {0, 0}, tempmv[2] = {0, 0};
-    short   *pred_mv1 = NULL;
-    short   *pred_mv2 = NULL;
-    short   *bi_mv1 = NULL, *bi_mv2 = NULL;
-    short   iterlist=list;
-    short   pred_mv_bi[2];
+    BiPredBlockMotionSearch(currMB, mv, pred_mv, ref, list, mb_x, mb_y, blocktype, search_range, apply_bi_weights, lambda_factor);
+  }
+
+#if GET_METIME
+  ftime(&tstruct2);   // end time ms
+  me_tmp_time=(tstruct2.time - tstruct1.time) * 1000 + (tstruct2.millitm - tstruct1.millitm);
+  me_tot_time += me_tmp_time;
+  me_time += me_tmp_time;
+#endif
+  return min_mcost;
+}
+
+
+/*!
+ ***********************************************************************
+ * \brief
+ *    Block bi-prediction motion search
+ ***********************************************************************
+ */
+int BiPredBlockMotionSearch(Macroblock *currMB,      //!< Current Macroblock
+                   short     mv[2],           //!< current list motion vector
+                   short*    pred_mv,         //!< current list motion vector predictor
+                   short     ref,             //!< reference idx
+                   int       list,            //!< reference picture list
+                   int       mb_x,            //!< x-coordinate inside macroblock
+                   int       mb_y,            //!< y-coordinate inside macroblock
+                   int       blocktype,       //!< block type (1-16x16 ... 7-4x4)
+                   int       search_range,    //!< 1-d search range for integer-position search
+                   int       apply_bi_weights, //!< apply bipred weights
+                   int*      lambda_factor)   //!< lagrangian parameter for determining motion cost
+{
+    int         iteration_no, i, j;
+    short       bipred_type = list ? 0 : 1;
+    short****** bipred_mv = img->bipred_mv[bipred_type];
+    int         min_mcostbi = INT_MAX;
+    short       bimv[2] = {0, 0}, tempmv[2] = {0, 0};
+    short*      pred_mv1 = NULL;
+    short*      pred_mv2 = NULL;
+    short*      bi_mv1 = NULL, *bi_mv2 = NULL;
+    short       iterlist=list;
+    short       pred_mv_bi[2];
+    int         block_x   = (mb_x>>2);
+    int         block_y   = (mb_y>>2);
+    int         bsx       = params->blc_size[blocktype][0];
+    int         bsy       = params->blc_size[blocktype][1];
+    int         pic_pix_x = img->opix_x + mb_x;
+    int         pic_pix_y = img->opix_y + mb_y;
+    int         list_offset = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? img->current_mb_nr % 2 ? 4 : 2 : 0;
 
     if (params->SearchMode == UM_HEX)
     {
       bipred_flag = 1;
-      UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, enc_picture->ref_idx[list ^ 1], enc_picture->mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy, &search_range);
+      UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, enc_picture->motion.ref_idx[list ^ 1], enc_picture->motion.mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy, &search_range);
     }
     else
-      SetMotionVectorPredictor     (currMB, pred_mv_bi, enc_picture->ref_idx[list ^ 1], enc_picture->mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy);
+      SetMotionVectorPredictor     (currMB, pred_mv_bi, enc_picture->motion.ref_idx[list ^ 1], enc_picture->motion.mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy);
 
     if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
     {
@@ -926,9 +976,9 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
     }
 
     //Bi-predictive motion Refinements
-    for (i=0; i <= params->BiPredMERefinements; i++)
+    for (iteration_no = 0; iteration_no <= params->BiPredMERefinements; iteration_no++)
     {
-      if (i & 0x01)
+      if (iteration_no & 0x01)
       {
         pred_mv1  = pred_mv;
         pred_mv2  = pred_mv_bi;
@@ -950,11 +1000,11 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
 
       PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, list_offset, ref);
       // Get bipred mvs for list iterlist given previously computed mvs from other list
-      min_mcostbi = BiPredME (currMB, orig_pic, ref, iterlist, list_offset, enc_picture->ref_idx, enc_picture->mv,
+      min_mcostbi = BiPredME (currMB, orig_pic, ref, iterlist, list_offset, enc_picture->motion.ref_idx, enc_picture->motion.mv,
         pic_pix_x, pic_pix_y, blocktype, pred_mv1, pred_mv2, bi_mv1, bi_mv2,
-        (params->BiPredMESearchRange <<(params->EPZSGrid))>>i, min_mcostbi, lambda_factor[F_PEL], apply_bi_weights);
+        (params->BiPredMESearchRange <<(params->EPZSGrid))>>iteration_no, min_mcostbi, iteration_no, lambda_factor[F_PEL], apply_bi_weights);
 
-      if (i > 0 && (tempmv[0] == bi_mv1[0]) && (tempmv[1] == bi_mv1[1]))
+      if (iteration_no > 0 && (tempmv[0] == bi_mv1[0]) && (tempmv[1] == bi_mv1[1]))
       {
         break;
       }
@@ -972,7 +1022,7 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
     {
       if (params->BiPredMESubPel)
       {
-        min_mcostbi = max_value;
+        min_mcostbi = INT_MAX;
         PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, list_offset, ref);
 
         min_mcostbi =  SubPelBiPredME (orig_pic, ref, iterlist, pic_pix_x, pic_pix_y, blocktype,
@@ -981,7 +1031,7 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
 
       if (params->BiPredMESubPel==2)
       {
-        min_mcostbi = max_value;
+        min_mcostbi = INT_MAX;
         PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist ^ 1, list_offset, ref);
 
         min_mcostbi =  SubPelBiPredME (orig_pic, ref, iterlist ^ 1, pic_pix_x, pic_pix_y, blocktype,
@@ -999,29 +1049,7 @@ BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
         bipred_mv[iterlist ^ 1][0][blocktype][j][i][1] = bi_mv2[1];
       }
     }
-  }
-
-#if GET_METIME
-  ftime(&tstruct2);   // end time ms
-  me_tmp_time=(tstruct2.time - tstruct1.time) * 1000 + (tstruct2.millitm - tstruct1.millitm);
-  me_tot_time += me_tmp_time;
-  me_time += me_tmp_time;
-#endif
-  return min_mcost;
-}
-
-int mv_bits_cost(short ***all_mv, short ***p_mv, int by, int bx, int step_v0, int step_v, int step_h0, int step_h, int mvd_bits)
-{
-  int v, h;
-  for (v=by; v<by + step_v0; v+=step_v)
-  {
-    for (h=bx; h<bx + step_h0; h+=step_h)
-    {
-      mvd_bits += mvbits[ all_mv[v][h][0] - p_mv[v][h][0] ];
-      mvd_bits += mvbits[ all_mv[v][h][1] - p_mv[v][h][1] ];
-    }
-  }
-  return mvd_bits;
+    return min_mcostbi;
 }
 
 /*!
@@ -1058,29 +1086,15 @@ int BIDPartitionCost (Macroblock *currMB,
   short   ***   p_mv_l1 = img->pred_mv[LIST_1][(int) cur_ref[LIST_1]][blocktype];
   short   *** all_mv_l0 = img->all_mv [LIST_0][(int) cur_ref[LIST_0]][blocktype];
   short   *** all_mv_l1 = img->all_mv [LIST_1][(int) cur_ref[LIST_1]][blocktype];
-
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  short bipred_me =  0; //no bipred for this case 
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
   //----- cost for motion vector bits -----
   // Should write a separate, small function to do this processing
   // List0 
-  for (v=by; v<by + step_v0; v+=step_v)
-  {
-    for (h=bx; h<bx + step_h0; h+=step_h)
-    {
-      mvd_bits += mvbits[ all_mv_l0[v][h][0] - p_mv_l0[v][h][0] ];
-      mvd_bits += mvbits[ all_mv_l0[v][h][1] - p_mv_l0[v][h][1] ];
-    }
-  }
+  mvd_bits = mv_bits_cost(all_mv_l0, p_mv_l0, by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);
   // List1
-  for (v=by; v<by + step_v0; v+=step_v)
-  {
-    for (h=bx; h<bx + step_h0; h+=step_h)
-    {
-      mvd_bits += mvbits[ all_mv_l1[v][h][0] - p_mv_l1[v][h][0] ];
-      mvd_bits += mvbits[ all_mv_l1[v][h][1] - p_mv_l1[v][h][1] ];
-    }
-  }
+  mvd_bits = mv_bits_cost(all_mv_l1, p_mv_l1, by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);
 
   mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
 
@@ -1091,13 +1105,13 @@ int BIDPartitionCost (Macroblock *currMB,
     for (bxx=0, h=bx; h<bx + step_h0; bxx+=4, h++)
     {
       pic_pix_x = img->opix_x + (block_x = (h<<2));
-      LumaPrediction (currMB, block_x, block_y, 4, 4, 2, blocktype, blocktype, (short) cur_ref[0], (short) cur_ref[1]);
+      LumaPrediction (currMB, block_x, block_y, 4, 4, 2, blocktype, blocktype, (short) cur_ref[0], (short) cur_ref[1], bipred_me);
 
       for (k=j=0; j<4; j++)
       {
         for (  i=0; i<4; i++)
           diff64[k++] = curr_blk[byy+j][bxx+i] =
-          pCurImg[pic_pix_y+j][pic_pix_x+i] - curr_mpr[j+block_y][i+block_x];
+          pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
       }
       if ((!params->Transform8x8Mode) || (blocktype>4))
         mcost += distortion4x4 (diff64);
@@ -1107,6 +1121,7 @@ int BIDPartitionCost (Macroblock *currMB,
   if (params->Transform8x8Mode && (blocktype<=4))  // tchen 4-29-04
   {
     for (byy=0; byy < params->blc_size[parttype][1]; byy+=bsy)
+    {
       for (bxx=0; bxx<params->blc_size[parttype][0]; bxx+=bsx)
       {
         for (k=0, j=byy;j<byy + 8;j++, k += 8)
@@ -1114,6 +1129,7 @@ int BIDPartitionCost (Macroblock *currMB,
 
         mcost += distortion8x8(diff64);
       }
+    }
   }
   return mcost;
 }
@@ -1132,35 +1148,37 @@ int GetSkipCostMB (Macroblock *currMB)
   int curr_diff[8][8];
   int mb_x, mb_y;
   int block;
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
   for(block = 0;block < 4;block++)
   {
     mb_y    = (block >>   1)<<3;
     mb_x    = (block & 0x01)<<3;
-    for (block_y=mb_y; block_y<mb_y+8; block_y+=4)
+    for (block_y = mb_y; block_y < mb_y+8; block_y += 4)
     {
       pic_pix_y = img->opix_y + block_y;
-      for (block_x=mb_x; block_x<mb_x+8; block_x+=4)
+      for (block_x = mb_x; block_x < mb_x + 8; block_x += 4)
       {
         pic_pix_x = img->opix_x + block_x;
 
         //===== prediction of 4x4 block =====
-        LumaPrediction (currMB, block_x, block_y, 4, 4, 0, 0, 0, 0, 0);
+        LumaPrediction (currMB, block_x, block_y, 4, 4, 0, 0, 0, 0, 0, 0);
 
         //===== get displaced frame difference ======
-        for (k=j=0; j<4; j++)
-          for (i=0; i<4; i++, k++)
+        for (k = j = 0; j < 4; j++)
+        {
+          for (i = 0; i < 4; i++, k++)
           {
-            diff[k] = curr_diff[block_y-mb_y+j][block_x-mb_x+i] = pCurImg[pic_pix_y+j][pic_pix_x+i] - curr_mpr[j+block_y][i+block_x];
+            diff[k] = curr_diff[block_y-mb_y+j][block_x-mb_x+i] = pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
           }
+        }
 
-          if(!((params->rdopt==0) && (params->Transform8x8Mode)))
-            cost += distortion4x4 (diff);
+        if(!((params->rdopt==0) && (params->Transform8x8Mode)))
+          cost += distortion4x4 (diff);
       }
     }
 
-    if((params->rdopt==0)&&(params->Transform8x8Mode))
+    if((params->rdopt == 0) && (params->Transform8x8Mode))
     {
       for(k=j=0; j<8; j++, k+=8)
         memcpy(&diff64[k], &(curr_diff[j]), 8 * sizeof(int));
@@ -1191,7 +1209,7 @@ void FindSkipModeMotionVector (Macroblock *currMB)
   int      a_ref_idx = 0;
   int      b_mv_y = 0;
   int      b_ref_idx = 0;
-  short    ***mv = enc_picture->mv[LIST_0];
+  short    ***mv = enc_picture->motion.mv[LIST_0];
   int *mb_size = img->mb_size[IS_LUMA];
 
 
@@ -1201,7 +1219,7 @@ void FindSkipModeMotionVector (Macroblock *currMB)
   if (mb_a.available)
   {
     a_mv_y    = mv[mb_a.pos_y][mb_a.pos_x][1];
-    a_ref_idx = enc_picture->ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];
+    a_ref_idx = enc_picture->motion.ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];
 
     if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
     {
@@ -1218,7 +1236,7 @@ void FindSkipModeMotionVector (Macroblock *currMB)
   if (mb_b.available)
   {
     b_mv_y    = mv[mb_b.pos_y][mb_b.pos_x][1];
-    b_ref_idx = enc_picture->ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];
+    b_ref_idx = enc_picture->motion.ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];
 
     if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
     {
@@ -1241,7 +1259,7 @@ void FindSkipModeMotionVector (Macroblock *currMB)
   }
   else
   {
-    SetMotionVectorPredictor (currMB, pmv, enc_picture->ref_idx[LIST_0], mv, 0, LIST_0, 0, 0, 16, 16);
+    SetMotionVectorPredictor (currMB, pmv, enc_picture->motion.ref_idx[LIST_0], mv, 0, LIST_0, 0, 0, 16, 16);
     for (bx = 0;bx < 4;bx++)
     {
       memcpy(all_mv [0][bx], pmv, 2* sizeof(short));
@@ -1265,7 +1283,8 @@ int GetDirectCost8x8 (Macroblock *currMB, int block, int *cost8x8)
   int cost  = 0;
   int mb_y  = (block/2)<<3;
   int mb_x  = (block%2)<<3;
-  imgpel  (*curr_mpr)[16] = img->mpr[0];
+  short bipred_me  = 0;
+  imgpel  (*mb_pred)[16] = img->mb_pred[0];
 
   for (block_y=mb_y; block_y<mb_y+8; block_y+=4)
   {
@@ -1286,21 +1305,21 @@ int GetDirectCost8x8 (Macroblock *currMB, int block, int *cost8x8)
       LumaPrediction (currMB, block_x, block_y, 4, 4,
         direct_pdir[pic_pix_y>>2][pic_pix_x>>2], 0, 0,
         direct_ref_idx[LIST_0][pic_pix_y>>2][pic_pix_x>>2],
-        direct_ref_idx[LIST_1][pic_pix_y>>2][pic_pix_x>>2]);
+        direct_ref_idx[LIST_1][pic_pix_y>>2][pic_pix_x>>2], bipred_me);
 
       //===== get displaced frame difference ======
       for (k=j=0; j<4; j++)
         for (i=0; i<4; i++, k++)
         {
           diff[k] = curr_diff[block_y-mb_y+j][block_x-mb_x+i] =
-            pCurImg[pic_pix_y+j][pic_pix_x+i] - curr_mpr[j+block_y][i+block_x];
+            pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
         }
 
         cost += distortion4x4 (diff);
     }
   }
 
-  if((params->rdopt==0)&&(params->Transform8x8Mode))
+  if((params->rdopt == 0) && (params->Transform8x8Mode))
   {
     k=0;
     for(j=0; j<8; j++, k+=8)
@@ -1405,8 +1424,8 @@ PartitionMotionSearch (Macroblock *currMB,
         search_range = params->search_range / ((imin(ref,1)+1) * imin(2,blocktype));
 
       //----- set arrays -----
-      ref_array = enc_picture->ref_idx[list];
-      mv_array  = enc_picture->mv[list];
+      ref_array = enc_picture->motion.ref_idx[list];
+      mv_array  = enc_picture->motion.mv[list];
 
       //----- init motion cost -----
       //motion_cost[blocktype][list][ref][block8x8] = 0;
@@ -1421,7 +1440,7 @@ PartitionMotionSearch (Macroblock *currMB,
         for (h=bx; h<bx+step_h0; h+=step_h)
         {
           all_mv = img->all_mv[list][ref][blocktype][v][h];
-          pic_block_x = img->block_x + h;          
+          pic_block_x = img->block_x + h;
 
           //--- motion search for block ---          
           if (Motion_Selected != 1)
@@ -1471,36 +1490,24 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
   int refList;
   int ref_idx;
 
-  byte  **   moving_block;
-  short ****   co_located_mv;
-  char  ***    co_located_ref_idx;
-  int64 ***    co_located_ref_id;
-  char  **     ref_pic_l0 = enc_picture->ref_idx[LIST_0];
-  char  **     ref_pic_l1 = enc_picture->ref_idx[LIST_1];
+  MotionParams *colocated;
+  char  **     ref_pic_l0 = enc_picture->motion.ref_idx[LIST_0];
+  char  **     ref_pic_l1 = enc_picture->motion.ref_idx[LIST_1];
 
   if (currMB->list_offset)
   {
     if(img->current_mb_nr%2)
     {
-      moving_block = Co_located->bottom_moving_block;
-      co_located_mv = Co_located->bottom_mv;
-      co_located_ref_idx = Co_located->bottom_ref_idx;
-      co_located_ref_id = Co_located->bottom_ref_pic_id;
+      colocated = &Co_located->bottom;
     }
     else
     {
-      moving_block = Co_located->top_moving_block;
-      co_located_mv = Co_located->top_mv;
-      co_located_ref_idx = Co_located->top_ref_idx;
-      co_located_ref_id = Co_located->top_ref_pic_id;
+      colocated = &Co_located->top;
     }
   }
   else
   {
-    moving_block = Co_located->moving_block;
-    co_located_mv = Co_located->mv;
-    co_located_ref_idx = Co_located->ref_idx;
-    co_located_ref_id = Co_located->ref_pic_id;
+    colocated = &Co_located->frame;
   }
 
   if (img->direct_spatial_mv_pred_flag)  //spatial direct mode copy from decoder
@@ -1626,10 +1633,10 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
     l1_refX = (l1_refX >= 0 && l1_refC >= 0) ? imin(l1_refX,l1_refC): imax(l1_refX,l1_refC);
 
     if (l0_refX >=0)
-      SetMotionVectorPredictor (currMB, pmvfw, enc_picture->ref_idx[LIST_0], enc_picture->mv[LIST_0], l0_refX, LIST_0, 0, 0, 16, 16);
+      SetMotionVectorPredictor (currMB, pmvfw, enc_picture->motion.ref_idx[LIST_0], enc_picture->motion.mv[LIST_0], l0_refX, LIST_0, 0, 0, 16, 16);
 
     if (l1_refX >=0)
-      SetMotionVectorPredictor (currMB, pmvbw, enc_picture->ref_idx[LIST_1], enc_picture->mv[LIST_1], l1_refX, LIST_1, 0, 0, 16, 16);
+      SetMotionVectorPredictor (currMB, pmvbw, enc_picture->motion.ref_idx[LIST_1], enc_picture->motion.mv[LIST_1], l1_refX, LIST_1, 0, 0, 16, 16);
 
     for (block_y=0; block_y<4; block_y++)
     {
@@ -1645,7 +1652,7 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
 
         if (l0_refX >=0)
         {
-          if (!l0_refX  && !moving_block[opic_block_y][opic_block_x])
+          if (!l0_refX  && !colocated->moving_block[opic_block_y][opic_block_x])
           {
             memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2 * sizeof(short));
             direct_ref_idx[LIST_0][pic_block_y][pic_block_x]=0;
@@ -1664,7 +1671,7 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
 
         if (l1_refX >=0)
         {
-          if(l1_refX==0 && !moving_block[opic_block_y][opic_block_x])
+          if(l1_refX==0 && !colocated->moving_block[opic_block_y][opic_block_x])
           {
             memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2 * sizeof(short));
             direct_ref_idx[LIST_1][pic_block_y][pic_block_x]= (char)l1_refX;
@@ -1748,8 +1755,8 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
         opic_block_x = (img->opix_x>>2) + block_x;
         all_mvs = img->all_mv;
 
-        refList = (co_located_ref_idx[LIST_0][opic_block_y][opic_block_x]== -1 ? LIST_1 : LIST_0);
-        ref_idx = co_located_ref_idx[refList][opic_block_y][opic_block_x];
+        refList = (colocated->ref_idx[LIST_0][opic_block_y][opic_block_x]== -1 ? LIST_1 : LIST_0);
+        ref_idx = colocated->ref_idx[refList][opic_block_y][opic_block_x];
 
         // next P is intra mode
         if (ref_idx==-1)
@@ -1768,7 +1775,7 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
 
           for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0+currMB->list_offset]);iref++)
           {
-            if (refpic[iref]==co_located_ref_id[refList ][opic_block_y][opic_block_x])
+            if (refpic[iref]==colocated->ref_pic_id[refList ][opic_block_y][opic_block_x])
             {
               mapped_idx=iref;
               break;
@@ -1786,18 +1793,18 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
             if (mv_scale==9999)
             {
               // forward
-              memcpy(all_mvs[LIST_0][0][0][block_y][block_x], co_located_mv[refList][opic_block_y][opic_block_x], 2* sizeof(short));
+              memcpy(all_mvs[LIST_0][0][0][block_y][block_x], colocated->mv[refList][opic_block_y][opic_block_x], 2* sizeof(short));
               // backward
               memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2* sizeof(short));
             }
             else
             {
               // forward
-              all_mvs[LIST_0][mapped_idx][0][block_y][block_x][0] = (mv_scale * co_located_mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8;
-              all_mvs[LIST_0][mapped_idx][0][block_y][block_x][1] = (mv_scale * co_located_mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8;
+              all_mvs[LIST_0][mapped_idx][0][block_y][block_x][0] = (mv_scale * colocated->mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8;
+              all_mvs[LIST_0][mapped_idx][0][block_y][block_x][1] = (mv_scale * colocated->mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8;
               // backward
-              all_mvs[LIST_1][         0][0][block_y][block_x][0] = ((mv_scale - 256)* co_located_mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8;
-              all_mvs[LIST_1][         0][0][block_y][block_x][1] = ((mv_scale - 256)* co_located_mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8;
+              all_mvs[LIST_1][         0][0][block_y][block_x][0] = ((mv_scale - 256)* colocated->mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8;
+              all_mvs[LIST_1][         0][0][block_y][block_x][1] = ((mv_scale - 256)* colocated->mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8;
             }
 
             // Test Level Limits if satisfied.
@@ -1842,4 +1849,3 @@ void Get_Direct_Motion_Vectors (Macroblock *currMB)
     }
   }
 }
-
diff --git a/lencod/src/nal.c b/lencod/src/nal.c
index 15794ad..b4b58b9 100644
--- a/lencod/src/nal.c
+++ b/lencod/src/nal.c
@@ -17,6 +17,7 @@
 
 #include "contributors.h"
 #include "global.h"
+#include "enc_statistics.h"
 
  /*!
  ************************************************************************
diff --git a/lencod/src/parset.c b/lencod/src/parset.c
index b25a12e..5f84804 100644
--- a/lencod/src/parset.c
+++ b/lencod/src/parset.c
@@ -101,7 +101,6 @@ void GenerateParameterSets (void)
     else
       GeneratePictureParameterSet( PicParSet[0], sps, 0, params->WeightedPrediction, params->WeightedBiprediction,
                                    params->chroma_qp_index_offset, 0);
-
   }
 
   active_sps = sps;
@@ -250,7 +249,7 @@ void GenerateSequenceParameterSet( seq_parameter_set_rbsp_t *sps, //!< Sequence
   }
 
   // Parameter Set ID hard coded to zero
-  sps->seq_parameter_set_id = 0;
+  sps->seq_parameter_set_id = SPS_id;
 
   // Fidelity Range Extensions stuff
   sps->bit_depth_luma_minus8   = params->output.bit_depth[0] - 8;
diff --git a/lencod/src/q_around.c b/lencod/src/q_around.c
new file mode 100644
index 0000000..e5271d9
--- /dev/null
+++ b/lencod/src/q_around.c
@@ -0,0 +1,369 @@
+
+/*!
+ *************************************************************************************
+ * \file q_around.c
+ *
+ * \brief
+ *    Quantization Adaptive Rounding (JVT-N011)
+ * \author
+ *    - Alexis Michael Tourapis    <alexismt@ieee.org>
+ *    - Ehsan Maani                <emaan@dolby.com>
+ *
+ *************************************************************************************
+ */
+
+#include "global.h"
+#include "memalloc.h"
+#include "q_offsets.h"
+#include "q_around.h"
+
+static const int AdaptRndCrPos[2][5] =
+{
+  //  P,   B,   I,  SP,  SI
+  {   4,   7,   1,   4,   1}, // Intra MB
+  {  10,  13,  10,  10,  10}  // Inter MB
+};
+
+static const int AdaptRndPos[4][5] =
+{
+  //  P,   B,   I,  SP,  SI
+  {   3,   6,   0,   3,   0}, // 4x4 Intra MB
+  {   1,   2,   0,   1,   2}, // 8x8 Intra MB
+  {   9,  12,   9,   9,   9}, // 4x4 Inter MB
+  {   3,   4,   3,   3,   3}, // 8x8 Inter MB
+};
+
+ARoundOffset bestOffset;
+
+int   **fadjust8x8 = NULL, **fadjust4x4 = NULL, ***fadjust4x4Cr = NULL, ***fadjust8x8Cr = NULL;
+
+static void allocate_offset_memory(InputParameters *params, ARoundOffset *offset)
+{
+  get_mem2Dint(&offset->InterFAdjust4x4, 16, 16);
+  get_mem2Dint(&offset->IntraFAdjust4x4, 16, 16);
+  get_mem2Dint(&offset->InterFAdjust8x8, 16, 16);
+  get_mem2Dint(&offset->IntraFAdjust8x8, 16, 16);
+
+  if (params->yuv_format != 0 )
+  {
+    if  (params->yuv_format == YUV444)
+    {
+      get_mem3Dint(&offset->InterFAdjust8x8Cr, 2, 16, 16);
+      get_mem3Dint(&offset->IntraFAdjust8x8Cr, 2, 16, 16);
+    }
+    get_mem3Dint(&offset->InterFAdjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
+    get_mem3Dint(&offset->IntraFAdjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
+  }
+}
+
+static void free_offset_memory(InputParameters *params, ARoundOffset *offset)
+{
+  free_mem2Dint(offset->InterFAdjust4x4);
+  free_mem2Dint(offset->IntraFAdjust4x4);
+  free_mem2Dint(offset->InterFAdjust8x8);
+  free_mem2Dint(offset->IntraFAdjust8x8);
+
+  if (params->yuv_format != 0 )
+  {
+    if  (params->yuv_format == YUV444)
+    {
+      free_mem3Dint(offset->InterFAdjust8x8Cr);
+      free_mem3Dint(offset->IntraFAdjust8x8Cr);
+    }
+    free_mem3Dint(offset->InterFAdjust4x4Cr);
+    free_mem3Dint(offset->IntraFAdjust4x4Cr);
+  }
+}
+
+
+void setup_adaptive_rounding (InputParameters *params)
+{
+  allocate_offset_memory(params, &bestOffset);
+
+  get_mem2Dint(&fadjust8x8, 16, 16);
+  get_mem2Dint(&fadjust4x4, 16, 16);
+  if (params->yuv_format != 0 )
+  {
+    get_mem3Dint(&fadjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
+    get_mem3Dint(&fadjust8x8Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
+  }
+}
+
+void clear_adaptive_rounding (InputParameters *params)
+{
+  free_offset_memory(params, &bestOffset);
+
+  free_mem2Dint(fadjust8x8);
+  free_mem2Dint(fadjust4x4);
+  if (params->yuv_format != 0)
+  {
+    free_mem3Dint(fadjust4x4Cr);
+    free_mem3Dint(fadjust8x8Cr);
+  }
+}
+
+void store_adaptive_rounding (ImageParameters *img, int block_y, int block_x)
+{
+  int j;
+
+  for (j = block_y; j < block_y + 4; j++)
+    memcpy(&fadjust4x4[j][block_x],&img->fadjust4x4[1][j][block_x], BLOCK_SIZE * sizeof(int));
+
+  if (img->P444_joined)
+  {
+    for (j = block_y; j < block_y + 4; j++)
+    {
+      memcpy(&fadjust4x4Cr[0][j][block_x],&img->fadjust4x4Cr[0][1][j][block_x], BLOCK_SIZE * sizeof(int));
+    }
+    for (j = block_y; j < block_y + 4; j++)
+    {
+      memcpy(&fadjust4x4Cr[1][j][block_x],&img->fadjust4x4Cr[1][1][j][block_x], BLOCK_SIZE * sizeof(int));
+    }
+  }
+}
+
+void update_adaptive_rounding(ImageParameters *img, int block_y, int block_x)
+{
+  int j;
+
+  for (j = block_y; j < block_y + BLOCK_SIZE; j++)
+    memcpy (&img->fadjust4x4[1][j][block_x],&fadjust4x4[j][block_x], BLOCK_SIZE * sizeof(int));
+
+  if (img->P444_joined)
+  {
+    for (j = 0; j < block_y + BLOCK_SIZE; j++)
+    {
+      memcpy (&img->fadjust4x4Cr[0][1][j][block_x],&fadjust4x4Cr[0][j][block_x], BLOCK_SIZE * sizeof(int));
+    }
+    for (j = 0; j < block_y + BLOCK_SIZE; j++)
+    {
+      memcpy (&img->fadjust4x4Cr[1][1][j][block_x],&fadjust4x4Cr[1][j][block_x], BLOCK_SIZE * sizeof(int));
+    }
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Store adaptive rounding luma parameters
+ *************************************************************************************
+ */
+
+void store_adaptive_rounding_parameters_luma (Macroblock *currMB, int mode)
+{
+   int is_inter = (mode != I4MB) && (mode != I16MB) && (mode != I8MB);
+
+  if (currMB->luma_transform_size_8x8_flag)
+  {
+    if ((mode == P8x8))
+      memcpy(&(bestOffset.InterFAdjust8x8[0][0]),&(img->fadjust8x8[2][0][0]), MB_PIXELS * sizeof(int));
+    else if (is_inter)
+      memcpy(&(bestOffset.InterFAdjust8x8[0][0]),&(img->fadjust8x8[0][0][0]), MB_PIXELS * sizeof(int));
+    else
+      memcpy(&(bestOffset.IntraFAdjust8x8[0][0]),&(img->fadjust8x8[1][0][0]), MB_PIXELS * sizeof(int));
+  }
+  else
+  {
+    if ((mode == P8x8))
+      memcpy(&(bestOffset.InterFAdjust4x4[0][0]),&(img->fadjust4x4[3][0][0]),MB_PIXELS * sizeof(int));
+    else if (is_inter)
+      memcpy(&(bestOffset.InterFAdjust4x4[0][0]),&(img->fadjust4x4[0][0][0]),MB_PIXELS * sizeof(int));
+    else
+      memcpy(&(bestOffset.IntraFAdjust4x4[0][0]),&(img->fadjust4x4[1 + mode == I16MB][0][0]),MB_PIXELS * sizeof(int));
+  }
+}
+
+
+/*!
+ *************************************************************************************
+ * \brief  
+ *    Store adaptive rounding chroma parameters
+ *************************************************************************************
+ */
+void store_adaptive_rounding_parameters_chroma (Macroblock *currMB, int mode)
+{
+  int j;
+  int is_inter = (mode != I4MB)&&(mode != I16MB)&&(mode != I8MB);
+
+  if (img->P444_joined)
+  {
+    if (currMB->luma_transform_size_8x8_flag)
+    {
+      if ((mode == P8x8))
+      {
+        memcpy(&(bestOffset.InterFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][2][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.InterFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][2][0][0]), MB_PIXELS * sizeof(int));
+      }
+      else if (is_inter)
+      {
+        memcpy(&(bestOffset.InterFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][0][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.InterFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][0][0][0]), MB_PIXELS * sizeof(int));
+      }
+      else
+      {
+        memcpy(&(bestOffset.IntraFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][1][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.IntraFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][1][0][0]), MB_PIXELS * sizeof(int));
+      }
+	}
+    else
+    {
+      if ((mode == P8x8))
+      {
+        memcpy(&(bestOffset.InterFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][3][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.InterFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][3][0][0]), MB_PIXELS * sizeof(int));
+      }
+      else if (is_inter)
+      {
+        memcpy(&(bestOffset.InterFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][0][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.InterFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][0][0][0]), MB_PIXELS * sizeof(int));
+      }
+      else
+      {
+        memcpy(&(bestOffset.IntraFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][1 + mode == I16MB][0][0]), MB_PIXELS * sizeof(int));
+        memcpy(&(bestOffset.IntraFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][1 + mode == I16MB][0][0]), MB_PIXELS * sizeof(int));
+      }
+    }
+  }
+
+  if ( (params->yuv_format == YUV420 || params->yuv_format == YUV422) && (params->AdaptRndChroma))  
+  {
+    if (currMB->luma_transform_size_8x8_flag && mode == P8x8)
+    {
+      for (j = 0; j < img->mb_cr_size_y; j++)
+      {
+        memcpy(bestOffset.InterFAdjust4x4Cr[0][j],img->fadjust8x8Cr[0][0][j],img->mb_cr_size_x * sizeof(int));
+        memcpy(bestOffset.InterFAdjust4x4Cr[1][j],img->fadjust8x8Cr[1][0][j],img->mb_cr_size_x * sizeof(int));
+      }
+    }
+    else if (mode == P8x8)
+    {
+      for (j = 0; j < img->mb_cr_size_y; j++)
+      {
+        memcpy(bestOffset.InterFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][2][j],img->mb_cr_size_x * sizeof(int));
+        memcpy(bestOffset.InterFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][2][j],img->mb_cr_size_x * sizeof(int));
+      }
+    }
+    else if (is_inter)
+    {
+      for (j = 0; j < img->mb_cr_size_y; j++)
+      {
+        memcpy(bestOffset.InterFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][0][j],img->mb_cr_size_x * sizeof(int));
+        memcpy(bestOffset.InterFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][0][j],img->mb_cr_size_x * sizeof(int));
+      }
+    }
+    else
+    {
+      for (j = 0; j < img->mb_cr_size_y; j++)
+      {
+        memcpy(bestOffset.IntraFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][1][j],img->mb_cr_size_x * sizeof(int));
+        memcpy(bestOffset.IntraFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][1][j],img->mb_cr_size_x * sizeof(int));
+      }
+    }
+  }
+}
+
+/*!
+ *************************************************************************************
+ * \brief
+ *    Store all adaptive rounding parameters
+ *************************************************************************************
+ */
+void store_adaptive_rounding_parameters (Macroblock *currMB, int mode)
+{
+  store_adaptive_rounding_parameters_luma (currMB, mode);
+  store_adaptive_rounding_parameters_chroma (currMB, mode);
+}
+
+/*!
+************************************************************************
+* \brief
+*    update rounding offsets based on JVT-N011
+************************************************************************
+*/
+void update_offset_params(Macroblock *currMB, int mode, int luma_transform_size_8x8_flag)
+{
+  int is_inter = (mode != I4MB)&&(mode != I16MB) && (mode != I8MB);
+  int luma_pos = AdaptRndPos[(is_inter<<1) + luma_transform_size_8x8_flag][img->type];
+  int i,j;
+  int qp = currMB->qp + img->bitdepth_luma_qp_scale;
+  int cur_qp = params->AdaptRoundingFixed ? 0 : qp;
+  int temp = 0;
+  int offsetRange = 1 << (OffsetBits - 1);
+  int blk_mask = 0x03 + (luma_transform_size_8x8_flag<<2);
+  int blk_shift = 2 + luma_transform_size_8x8_flag;
+  short **offsetList = luma_transform_size_8x8_flag ? OffsetList8x8[cur_qp] : OffsetList4x4[cur_qp];
+
+  int **fAdjust = is_inter
+    ? (luma_transform_size_8x8_flag ? bestOffset.InterFAdjust8x8 : bestOffset.InterFAdjust4x4)
+    : (luma_transform_size_8x8_flag ? bestOffset.IntraFAdjust8x8 : bestOffset.IntraFAdjust4x4);
+
+  if( (active_sps->chroma_format_idc == YUV444) && IS_INDEPENDENT(params) )
+  {
+    if( luma_transform_size_8x8_flag )  // 8x8
+      luma_pos += 5 * img->colour_plane_id;
+    else  // 4x4
+      luma_pos += img->colour_plane_id;
+  }
+
+  for (j=0; j < MB_BLOCK_SIZE; j++)
+  {
+    int j_pos = ((j & blk_mask)<<blk_shift);
+    for (i=0; i < MB_BLOCK_SIZE; i++)
+    {
+      temp = j_pos + (i & blk_mask);
+      offsetList[luma_pos][temp] += fAdjust[j][i];
+      offsetList[luma_pos][temp]  = iClip3(0, offsetRange, offsetList[luma_pos][temp]);
+    }
+  }
+
+  if(img->P444_joined)
+  { 
+    int ***fAdjustCbCr = (int ***) (is_inter
+      ? (luma_transform_size_8x8_flag ? bestOffset.InterFAdjust8x8Cr : bestOffset.InterFAdjust4x4Cr)
+      : (luma_transform_size_8x8_flag ? bestOffset.IntraFAdjust8x8Cr : bestOffset.IntraFAdjust4x4Cr));
+    int uv;
+
+    for(uv = 0; uv < 2; uv++)
+    {
+      luma_pos = AdaptRndPos[(is_inter<<1) + luma_transform_size_8x8_flag][img->type];
+      if(luma_transform_size_8x8_flag )  // 8x8
+        luma_pos += 5 * (uv+1);
+      else  // 4x4
+        luma_pos += (uv+1);
+      for (j=0; j < MB_BLOCK_SIZE; j++)
+      {
+        int j_pos = ((j & blk_mask)<<blk_shift);
+        for (i=0; i < MB_BLOCK_SIZE; i++)
+        {
+          temp = j_pos + (i & blk_mask);
+          offsetList[luma_pos][temp] += fAdjustCbCr[uv][j][i];
+          offsetList[luma_pos][temp] = iClip3(0,offsetRange,offsetList[luma_pos][temp]);
+        }
+      }
+    }
+  }
+
+  if ((params->AdaptRndChroma) && (params->yuv_format == YUV420 || params->yuv_format == YUV422 ))
+  {
+    int u_pos = AdaptRndCrPos[is_inter][img->type];
+    int v_pos = u_pos + 1;
+    int jpos;
+
+    int ***fAdjustCr = is_inter ? bestOffset.InterFAdjust4x4Cr : bestOffset.IntraFAdjust4x4Cr;
+
+    for (j = 0; j < img->mb_cr_size_y; j++)
+    {
+      jpos = ((j & 0x03)<<2);
+      for (i = 0; i < img->mb_cr_size_x; i++)
+      {
+        temp = jpos + (i & 0x03);
+        OffsetList4x4[cur_qp][u_pos][temp] += fAdjustCr[0][j][i];
+        OffsetList4x4[cur_qp][u_pos][temp]  = iClip3(0,offsetRange,OffsetList4x4[cur_qp][u_pos][temp]);
+        OffsetList4x4[cur_qp][v_pos][temp] += fAdjustCr[1][j][i];
+        OffsetList4x4[cur_qp][v_pos][temp]  = iClip3(0,offsetRange,OffsetList4x4[cur_qp][v_pos][temp]);
+      }
+    }
+  }
+}
+
+
diff --git a/lencod/src/q_matrix.c b/lencod/src/q_matrix.c
index 568cd1d..a0c7177 100644
--- a/lencod/src/q_matrix.c
+++ b/lencod/src/q_matrix.c
@@ -16,11 +16,153 @@ extern char *GetConfigFileContent (char *Filename, int error_type);
 
 #define MAX_ITEMS_TO_PARSE  1000
 
-extern const int quant_coef[6][4][4];
-extern const int dequant_coef[6][4][4];
+const int quant_coef[6][4][4] = {
+  {{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243},{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243}},
+  {{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660},{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660}},
+  {{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194},{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194}},
+  {{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647},{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647}},
+  {{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355},{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355}},
+  {{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893},{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893}}
+};
+
+const int dequant_coef[6][4][4] = {
+  {{10, 13, 10, 13},{ 13, 16, 13, 16},{10, 13, 10, 13},{ 13, 16, 13, 16}},
+  {{11, 14, 11, 14},{ 14, 18, 14, 18},{11, 14, 11, 14},{ 14, 18, 14, 18}},
+  {{13, 16, 13, 16},{ 16, 20, 16, 20},{13, 16, 13, 16},{ 16, 20, 16, 20}},
+  {{14, 18, 14, 18},{ 18, 23, 18, 23},{14, 18, 14, 18},{ 18, 23, 18, 23}},
+  {{16, 20, 16, 20},{ 20, 25, 20, 25},{16, 20, 16, 20},{ 20, 25, 20, 25}},
+  {{18, 23, 18, 23},{ 23, 29, 23, 29},{18, 23, 18, 23},{ 23, 29, 23, 29}}
+};
+
+const int quant_coef8[6][8][8] =
+{
+  {
+    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
+    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
+    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
+    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
+    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
+    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
+    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
+    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428}
+  },
+  {
+    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
+    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
+    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
+    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
+    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
+    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
+    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
+    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826}
+  },
+  {
+    {10082, 9675, 12710,  9675, 10082,  9675, 12710,  9675},
+    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
+    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
+    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
+    {10082, 9675, 12710,  9675, 10082,  9675, 12710,  9675},
+    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943},
+    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
+    {9675,  8943, 11985,  8943, 9675, 8943, 11985,  8943}
+  },
+  {
+    {9362,  8931, 11984,  8931, 9362, 8931, 11984,  8931},
+    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
+    {11984, 11259,  14913,  11259,  11984,  11259,  14913,  11259},
+    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
+    {9362,  8931, 11984,  8931, 9362, 8931, 11984,  8931},
+    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228},
+    {11984, 11259,  14913,  11259,  11984,  11259,  14913,  11259},
+    {8931,  8228, 11259,  8228, 8931, 8228, 11259,  8228}
+  },
+  {
+    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
+    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
+    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
+    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
+    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
+    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
+    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
+    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346}
+  },
+  {
+    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
+    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
+    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
+    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
+    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
+    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
+    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
+    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428}
+  }
+};
+
+
 
-extern const int quant_coef8[6][8][8];
-extern const int dequant_coef8[6][8][8];
+const int dequant_coef8[6][8][8] =
+{
+  {
+    {20,  19, 25, 19, 20, 19, 25, 19},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {25,  24, 32, 24, 25, 24, 32, 24},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {20,  19, 25, 19, 20, 19, 25, 19},
+    {19,  18, 24, 18, 19, 18, 24, 18},
+    {25,  24, 32, 24, 25, 24, 32, 24},
+    {19,  18, 24, 18, 19, 18, 24, 18}
+  },
+  {
+    {22,  21, 28, 21, 22, 21, 28, 21},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {22,  21, 28, 21, 22, 21, 28, 21},
+    {21,  19, 26, 19, 21, 19, 26, 19},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {21,  19, 26, 19, 21, 19, 26, 19}
+  },
+  {
+    {26,  24, 33, 24, 26, 24, 33, 24},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {33,  31, 42, 31, 33, 31, 42, 31},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {26,  24, 33, 24, 26, 24, 33, 24},
+    {24,  23, 31, 23, 24, 23, 31, 23},
+    {33,  31, 42, 31, 33, 31, 42, 31},
+    {24,  23, 31, 23, 24, 23, 31, 23}
+  },
+  {
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {35,  33, 45, 33, 35, 33, 45, 33},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {28,  26, 35, 26, 28, 26, 35, 26},
+    {26,  25, 33, 25, 26, 25, 33, 25},
+    {35,  33, 45, 33, 35, 33, 45, 33},
+    {26,  25, 33, 25, 26, 25, 33, 25}
+  },
+  {
+    {32,  30, 40, 30, 32, 30, 40, 30},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {40,  38, 51, 38, 40, 38, 51, 38},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {32,  30, 40, 30, 32, 30, 40, 30},
+    {30,  28, 38, 28, 30, 28, 38, 28},
+    {40,  38, 51, 38, 40, 38, 51, 38},
+    {30,  28, 38, 28, 30, 28, 38, 28}
+  },
+  {
+    {36,  34, 46, 34, 36, 34, 46, 34},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {46,  43, 58, 43, 46, 43, 58, 43},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {36,  34, 46, 34, 36, 34, 46, 34},
+    {34,  32, 43, 32, 34, 32, 43, 32},
+    {46,  43, 58, 43, 46, 43, 58, 43},
+    {34,  32, 43, 32, 34, 32, 43, 32}
+  }
+};
 
 
 int matrix4x4_check[6] = {0, 0, 0, 0, 0, 0};
diff --git a/lencod/src/q_offsets.c b/lencod/src/q_offsets.c
index 5d100c0..9f1989a 100644
--- a/lencod/src/q_offsets.c
+++ b/lencod/src/q_offsets.c
@@ -159,7 +159,7 @@ static const short Offset8_inter_default[64] = {
 void allocate_QOffsets ()
 {
   int max_bitdepth = imax(params->output.bit_depth[0], params->output.bit_depth[1]);
-  int max_qp = (3 + 6*(max_bitdepth) - MIN_QP);
+  int max_qp = (3 + 6*(max_bitdepth));
 
   get_mem5Dint(&LevelOffset4x4Comp, 3, 2, max_qp + 1, 4, 4);
   get_mem5Dint(&LevelOffset8x8Comp, 3, 2, max_qp + 1, 8, 8);
@@ -428,8 +428,8 @@ void Init_QOffsetMatrix ()
 void InitOffsetParam ()
 {
   int i, k;
-  int max_qp_luma = (4 + 6*(params->output.bit_depth[0]) - MIN_QP);
-  int max_qp_cr   = (4 + 6*(params->output.bit_depth[1]) - MIN_QP);
+  int max_qp_luma = (4 + 6*(params->output.bit_depth[0]));
+  int max_qp_cr   = (4 + 6*(params->output.bit_depth[1]));
 
   for (i = 0; i < (params->AdaptRoundingFixed ? 1 : imax(max_qp_luma, max_qp_cr)); i++)
   {
@@ -496,7 +496,7 @@ void CalculateOffsetParam ()
   int img_type = (img->type == SI_SLICE ? I_SLICE : (img->type == SP_SLICE ? P_SLICE : img->type));
 
   int max_qp_scale = imax(img->bitdepth_luma_qp_scale, img->bitdepth_chroma_qp_scale);
-  int max_qp = 51 + max_qp_scale - MIN_QP;
+  int max_qp = 51 + max_qp_scale;
 
   AdaptRndWeight = params->AdaptRndWFactor[img->nal_reference_idc != 0][img_type];
   AdaptRndCrWeight = params->AdaptRndCrWFactor[img->nal_reference_idc != 0][img_type];
@@ -630,7 +630,7 @@ void CalculateOffset8Param ()
   int q_bits, qp;
 
   int max_qp_scale = imax(img->bitdepth_luma_qp_scale, img->bitdepth_chroma_qp_scale);
-  int max_qp = 51 + max_qp_scale - MIN_QP;
+  int max_qp = 51 + max_qp_scale;
 
   if (img->type == I_SLICE || img->type == SI_SLICE )
   {
diff --git a/lencod/src/quant4x4.c b/lencod/src/quant4x4.c
index a3a6dac..25e2828 100644
--- a/lencod/src/quant4x4.c
+++ b/lencod/src/quant4x4.c
@@ -24,28 +24,25 @@
 *
 ************************************************************************
 */
-void init_quant_4x4(ImageParameters *img)
+void init_quant_4x4(InputParameters *params, ImageParameters *img)
 {
   if (params->UseRDOQuant == 1)
   {
     quant_4x4     = quant_4x4_trellis;
+    quant_dc4x4   = quant_dc4x4_trellis;
     quant_ac4x4   = quant_ac4x4_trellis;
-    if (params->RDOQ_CR == 1)
-      quant_ac4x4cr = quant_ac4x4_trellis;
-    else
-      quant_ac4x4cr = quant_ac4x4_normal;
   }
   else if (img->AdaptiveRounding)
   {
-    quant_4x4   = quant_4x4_around;
-    quant_ac4x4 = quant_ac4x4_around;
-    quant_ac4x4cr = quant_ac4x4_around;
+    quant_4x4     = quant_4x4_around;
+    quant_dc4x4   = quant_dc4x4_normal;
+    quant_ac4x4   = quant_ac4x4_around;
   }
   else
   {
     quant_4x4   = quant_4x4_normal;
+    quant_dc4x4 = quant_dc4x4_normal;
     quant_ac4x4 = quant_ac4x4_normal;
-    quant_ac4x4cr = quant_ac4x4_normal;
   }
 }
 
diff --git a/lencod/src/quant4x4_around.c b/lencod/src/quant4x4_around.c
index 6a105ba..a108075 100644
--- a/lencod/src/quant4x4_around.c
+++ b/lencod/src/quant4x4_around.c
@@ -9,6 +9,7 @@
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
  *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *    - Limin Liu                                <limin.liu@dolby.com>
  *
  *************************************************************************************
  */
@@ -65,36 +66,44 @@ int quant_4x4_around(int (*tblock)[16], int block_y, int block_x, int  qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
 
-    if (level != 0)
+    if (*m7 != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
-        level = imin(level, CAVLC_LEVEL_LIMIT);
-
-      fadjust4x4[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), q_bits + 1);
-
-      nonzero = TRUE;
-
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
-
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
-      // inverse scale can be alternative performed as follows to ensure 16bit
-      // arithmetic is satisfied.
-      // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        fadjust4x4[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), q_bits + 1);
+
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
+        // inverse scale can be alternative performed as follows to ensure 16bit
+        // arithmetic is satisfied.
+        // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+        nonzero = TRUE;        
+      }
+      else
+      {
+        fadjust4x4[j][block_x + i] = 0;
+        run++;
+        *m7 = 0;
+      } 
     }
     else
     {
       fadjust4x4[j][block_x + i] = 0;
       run++;
-      *m7 = 0;
-    }      
+    } 
   }
 
   *ACL = 0;
@@ -105,7 +114,7 @@ int quant_4x4_around(int (*tblock)[16], int block_y, int block_x, int  qp,
 int quant_ac4x4_around(int (*tblock)[16], int block_y, int block_x, int qp,
                        int*  ACLevel, int*  ACRun, 
                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost)
+                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type)
 {
   static int i,j, coeff_ctr;
 
@@ -127,39 +136,116 @@ int quant_ac4x4_around(int (*tblock)[16], int block_y, int block_x, int qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-    if (level != 0)
+    if (*m7 != 0)
+    {
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        fadjust4x4[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
+
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
+        // inverse scale can be alternative performed as follows to ensure 16bit
+        // arithmetic is satisfied.
+        // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        fadjust4x4[j][block_x + i] = 0;
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
     {
-    if (params->symbol_mode == CAVLC && img->qp < 10)
-      level = imin(level, CAVLC_LEVEL_LIMIT);
+      fadjust4x4[j][block_x + i] = 0;
+      run++;
+    }          
+  }
 
-      fadjust4x4[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
-      nonzero = TRUE;
+  *ACL = 0;
+
+  return nonzero;
+}
+ 
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 4x4 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x4_around(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
 
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
 
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
-      // inverse scale can be alternative performed as follows to ensure 16bit
-      // arithmetic is satisfied.
-      // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
-      *ACL++ = level;
-      *ACR++ = run; 
+  // Quantization
+  for (coeff_ctr = 0; coeff_ctr < 16; coeff_ctr++)
+  {
+    i = *p_scan++;  // horizontal position
+    j = *p_scan++;  // vertical position
+
+    m7 = &tblock[j][i];
+    
+    if (*m7 != 0)
+    {    
+    scaled_coeff = iabs (*m7) * levelscale;
+    level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+    if (level != 0)
+    {
+      if (params->symbol_mode == CAVLC)
+        level = imin(level, CAVLC_LEVEL_LIMIT);
+      level = isignab(level, *m7);
+
+      *m7 = level;
+      *DCL++  = level;
+      *DCR++  = run;
       // reset zero level counter
-      run    = 0;
+      run     = 0;
+      nonzero = TRUE;
     }
     else
     {
-      fadjust4x4[j][block_x + i] = 0;
       run++;
       *m7 = 0;
-    }      
+    }
+  }
+    else
+    {
+      run++;
+    }                    
   }
 
-  *ACL = 0;
+  *DCL = 0;
 
   return nonzero;
 }
- 
diff --git a/lencod/src/quant4x4_normal.c b/lencod/src/quant4x4_normal.c
index 378b190..e510073 100644
--- a/lencod/src/quant4x4_normal.c
+++ b/lencod/src/quant4x4_normal.c
@@ -9,6 +9,7 @@
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
  *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *    - Limin Liu                                <limin.liu@dolby.com>
  *
  *************************************************************************************
  */
@@ -64,33 +65,40 @@ int quant_4x4_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
 
-    if (level != 0)
+    if (*m7 != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
-        level = imin(level, CAVLC_LEVEL_LIMIT);
-
-      nonzero = TRUE;
-
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
-
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
-      // inverse scale can be alternative performed as follows to ensure 16bit
-      // arithmetic is satisfied.
-      // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
+        // inverse scale can be alternative performed as follows to ensure 16bit
+        // arithmetic is satisfied.
+        // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+        nonzero = TRUE;        
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
     }
     else
     {
       run++;
-      *m7 = 0;
-    }      
+    }          
   }
 
   *ACL = 0;
@@ -101,7 +109,7 @@ int quant_4x4_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
 int quant_ac4x4_normal(int (*tblock)[16], int block_y, int block_x, int qp,                 
                        int*  ACLevel, int*  ACRun, 
                        int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost)
+                       int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type)
 {
   static int i,j, coeff_ctr;
 
@@ -123,37 +131,115 @@ int quant_ac4x4_normal(int (*tblock)[16], int block_y, int block_x, int qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-    if (level != 0)
+    if (*m7 != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
-        level = imin(level, CAVLC_LEVEL_LIMIT);
-
-      nonzero = TRUE;
-
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
-
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
-      // inverse scale can be alternative performed as follows to ensure 16bit
-      // arithmetic is satisfied.
-      // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 4);
+        // inverse scale can be alternative performed as follows to ensure 16bit
+        // arithmetic is satisfied.
+        // *m7 = (qp_per<4) ? rshift_rnd_sf((level*invlevelscale[j][i]),4-qp_per) : (level*invlevelscale[j][i])<<(qp_per-4);
+        *ACL++  = level;
+        *ACR++  = run; 
+        // reset zero level counter
+        run     = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
     }
     else
     {
       run++;
-      *m7 = 0;
-    }      
+    }          
   }
 
   *ACL = 0;
 
   return nonzero;
 }
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 4x4 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x4_normal(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  // Quantization
+  for (coeff_ctr = 0; coeff_ctr < 16; coeff_ctr++)
+  {
+    i = *p_scan++;  // horizontal position
+    j = *p_scan++;  // vertical position
+
+    m7 = &tblock[j][i];
+
+    if (*m7 != 0)
+    {
+      scaled_coeff = iabs (*m7) * levelscale;
+      level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        level = isignab(level, *m7);
+
+        *m7     = level;
+        *DCL++  = level;
+        *DCR++  = run;
+        // reset zero level counter
+        run     = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
+    {
+      run++;
+    }                    
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
  
diff --git a/lencod/src/quant4x4_trellis.c b/lencod/src/quant4x4_trellis.c
index e4ccc8b..93cc524 100644
--- a/lencod/src/quant4x4_trellis.c
+++ b/lencod/src/quant4x4_trellis.c
@@ -8,6 +8,8 @@
  *
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Qualcomm                                        
+ *    - Limin Liu                                <limin.liu@dolby.com>
  *
  *************************************************************************************
  */
@@ -28,7 +30,7 @@
 #include "quant4x4.h"
 #include "rdo_quant.h"
 
-const int estErr4x4[6][4][4]=
+const int estErr4x4[6][4][4] =
 {
   {
     {25600, 27040, 25600, 27040}, 
@@ -69,10 +71,11 @@ const int estErr4x4[6][4][4]=
 };
 
 
-void rdoq_4x4(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem, 
+void rdoq_4x4(int (*tblock)[16], int block_y, int block_x, int qp_per, int qp_rem, 
               int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16]);
-void rdoq_ac4x4(int (*tblock)[16] , int block_x, int qp_per, int qp_rem, 
-                int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16]);
+
+void rdoq_ac4x4(int (*tblock)[16] , int block_y, int block_x, int qp_per, int qp_rem, 
+                int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16], int type);
 
 /*!
  ************************************************************************
@@ -102,9 +105,9 @@ int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
   int*  ACL = &ACLevel[0];
   int*  ACR = &ACRun[0];
   
-  int levelTrellis[16];
+  static int levelTrellis[16];
 
-  rdoq_4x4(tblock,block_y,block_x,qp_per,qp_rem,levelscale,leveloffset,pos_scan, levelTrellis);
+  rdoq_4x4(tblock, block_y, block_x, qp_per, qp_rem, levelscale, leveloffset, pos_scan, levelTrellis);
 
   // Quantization
   for (coeff_ctr = 0; coeff_ctr < 16; coeff_ctr++)
@@ -113,6 +116,8 @@ int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
+    if (*m7 != 0)
+    {    
     /*
     scaled_coeff = iabs (*m7) * levelscale[j][i];
     level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
@@ -121,7 +126,7 @@ int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
 
     if (level != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
+      if (params->symbol_mode == CAVLC)
         level = imin(level, CAVLC_LEVEL_LIMIT);
 
       nonzero = TRUE;
@@ -139,7 +144,12 @@ int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
     {
       run++;
       *m7 = 0;
-    }      
+    }
+    }
+    else
+    {
+      run++;
+    }                    
   }
 
   *ACL = 0;
@@ -155,23 +165,15 @@ int quant_4x4_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
 *
 ************************************************************************
 */
-void rdoq_4x4(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem, 
-              int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16])
+void rdoq_4x4(int (*tblock)[16], int block_y, int block_x, int qp_per, int qp_rem, 
+              int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[])
 {
-  static int i,j, coeff_ctr;
-
-  static int *m7;
-
-  int level;
-
-  int q_bits = Q_BITS + qp_per;
-
-  int m4[4][4], ii;
+  const byte *p_scan = &pos_scan[0][0];
   levelDataStruct levelData[16];
-  double  lambda_md=0, normFact=pow(2,(2*DQ_BITS+19));
-  double err;
-  int lowerInt, kStart=0, kStop=0, noCoeff = 0, estBits;
+  double  lambda_md = 0;
+  int kStart=0, kStop=0, noCoeff = 0, estBits;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
+  int type = LUMA_4x4;
 
   if ((img->type==B_SLICE) && img->nal_reference_idc)
   {
@@ -182,69 +184,26 @@ void rdoq_4x4(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem
     lambda_md = img->lambda_md[img->type][img->masterQP]; 
   }
 
-  for (coeff_ctr = 0; coeff_ctr < 16; coeff_ctr++)
-  {
-    i = pos_scan[coeff_ctr][0];
-    j = pos_scan[coeff_ctr][1];
-
-    m7 = &tblock[j][block_x];
-    m4[j][i] = m7[i];
-  } 
-  
-  for (coeff_ctr=0;coeff_ctr < 16; coeff_ctr++)
-  {
-    i=pos_scan[coeff_ctr][0];
-    j=pos_scan[coeff_ctr][1];
-
-    levelData[coeff_ctr].levelDouble = iabs(m4[j][i] * levelscale[i][j]);
-    level=(levelData[coeff_ctr].levelDouble>>q_bits);
-
-    lowerInt=(((int)levelData[coeff_ctr].levelDouble - (level<<q_bits))<(1<<(q_bits-1)))? 1 : 0;
-
-    levelData[coeff_ctr].level[0]=0;
-    if (level==0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].noLevels=1;
-    }
-    else if (level==0 && lowerInt==0)
-    {
-      levelData[coeff_ctr].level[1] = level+1;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
-    }
-    else if (level>0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
-    }
-    else
-    {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].level[2] = level+1;
-      levelData[coeff_ctr].noLevels=3;
-      kStop=coeff_ctr;
-      kStart=coeff_ctr;
-      noCoeff++;
-    }
-
-    for (ii=0; ii<levelData[coeff_ctr].noLevels; ii++)
-    {
-      err=(double)(levelData[coeff_ctr].level[ii]<<q_bits)-(double)levelData[coeff_ctr].levelDouble;
-      levelData[coeff_ctr].errLevel[ii] = (err * err * (double) estErr4x4[qp_rem][i][j]) / normFact; 
-    }
-  }
-
-  estBits=est_write_and_store_CBP_block_bit(currMB, LUMA_4x4, block_y, block_x);
+  noCoeff = init_trellis_data(tblock, block_x, qp_per, qp_rem, levelscale, leveloffset, p_scan, currMB, levelData, &kStart, &kStop, type);
+  estBits = est_write_and_store_CBP_block_bit(currMB, LUMA_4x4);
   est_writeRunLevel_CABAC(levelData, levelTrellis, LUMA_4x4, lambda_md, kStart, kStop, noCoeff, estBits);
 }
 
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 4x4 block (LUMA_16AC or CHROMA_AC)
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
 int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,                
                         int*  ACLevel, int*  ACRun, 
                         int **fadjust4x4, int **levelscale, int **invlevelscale, int **leveloffset,
-                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost)
+                        int *coeff_cost, const byte (*pos_scan)[2], const byte *c_cost, int type)
 {
   static int i,j, coeff_ctr;
 
@@ -257,9 +216,9 @@ int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,
   int*  ACL = &ACLevel[0];
   int*  ACR = &ACRun[0];
 
-  int levelTrellis[16]; 
+  static int levelTrellis[16]; 
 
-  rdoq_ac4x4(tblock, block_x, qp_per, qp_rem, levelscale, leveloffset, pos_scan, levelTrellis);
+  rdoq_ac4x4(tblock, block_y, block_x, qp_per, qp_rem, levelscale, leveloffset, pos_scan, levelTrellis, type);
 
   // Quantization
   for (coeff_ctr = 1; coeff_ctr < 16; coeff_ctr++)
@@ -268,19 +227,19 @@ int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
+    if (*m7 != 0)
+    {    
     /*
     scaled_coeff = iabs (*m7) * levelscale[j][i];
     level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
     */
-    level=levelTrellis[coeff_ctr-1];
+    level=levelTrellis[coeff_ctr - 1];
 
     if (level != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
+      if (params->symbol_mode == CAVLC)
         level = imin(level, CAVLC_LEVEL_LIMIT);
 
-      nonzero = TRUE;
-
       *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
 
       level  = isignab(level, *m7);
@@ -292,12 +251,18 @@ int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,
       *ACR++ = run; 
       // reset zero level counter
       run    = 0;
+        nonzero = TRUE;
     }
     else
     {
       run++;
       *m7 = 0;
-    }      
+    }
+    }
+    else
+    {
+      run++;
+    }              
   }
 
   *ACL = 0;
@@ -305,23 +270,21 @@ int quant_ac4x4_trellis(int (*tblock)[16], int block_y, int block_x, int qp,
   return nonzero;
 }
 
-void rdoq_ac4x4(int (*tblock)[16] , int block_x, int qp_per, int qp_rem, 
-                int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[16])
+/*!
+************************************************************************
+* \brief
+*    Rate distortion optimized Quantization process for 
+*    all coefficients in a 4x4 block (LUMA_16AC or CHROMA_AC)
+*
+************************************************************************
+*/
+void rdoq_ac4x4(int (*tblock)[16] , int block_y, int block_x, int qp_per, int qp_rem, 
+                int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[], int type)
 {
-  static int i,j, coeff_ctr;
-
-  static int *m7;
-
-  int level;
-
-  int q_bits = Q_BITS + qp_per;
   const byte *p_scan = &pos_scan[1][0];
-
-  int k;
   levelDataStruct levelData[16];
-  double  lambda_md=0, normFact=pow(2,(2*DQ_BITS+19));
-  double err;
-  int lowerInt, kStart=0, kStop=0, noCoeff=0, estBits;
+  double  lambda_md=0;
+  int kStart = 0, kStop = 0, noCoeff = 0, estBits;
   Macroblock *currMB = &img->mb_data[img->current_mb_nr];
 
   if ((img->type==B_SLICE) && img->nal_reference_idc)
@@ -333,59 +296,82 @@ void rdoq_ac4x4(int (*tblock)[16] , int block_x, int qp_per, int qp_rem,
     lambda_md = img->lambda_md[img->type][img->masterQP]; 
   }
 
-  for (coeff_ctr=0;coeff_ctr < 15;coeff_ctr++)
+  noCoeff = init_trellis_data(tblock, block_x, qp_per, qp_rem, levelscale, leveloffset, p_scan, currMB, levelData, &kStart, &kStop, type);
+  estBits = est_write_and_store_CBP_block_bit(currMB, type);
+  est_writeRunLevel_CABAC(levelData, levelTrellis, type, lambda_md, kStart, kStop, noCoeff, estBits);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 4x4 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x4_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int levelscale, int invlevelscale, int **leveloffset, const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;
+  int   qp_per = qp_per_matrix[qp];
+  int   qp_rem = qp_rem_matrix[qp];
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+  
+  static int levelTrellis[16];
+
+  rdoq_dc(tblock,qp_per,qp_rem, levelscale, leveloffset,pos_scan, levelTrellis, LUMA_16DC);
+
+  // Quantization
+  for (coeff_ctr = 0; coeff_ctr < 16; coeff_ctr++)
   {
-   // i=pos_scan[coeff_ctr+1][0]; // scan is shifted due to DC
-    //j=pos_scan[coeff_ctr+1][1]; // scan is shifted due to DC
     i = *p_scan++;  // horizontal position
     j = *p_scan++;  // vertical position
-    m7 = &tblock[j][block_x + i];
 
+    m7 = &tblock[j][i];
 
-    levelData[coeff_ctr].levelDouble=iabs(*m7 * levelscale[i][j]);
-    level=(levelData[coeff_ctr].levelDouble>>q_bits);
+    if (*m7 != 0)
+    {    
+      level = levelTrellis[coeff_ctr];
 
-    lowerInt=(((int)levelData[coeff_ctr].levelDouble - (level<<q_bits))<(1<<(q_bits-1)))? 1 : 0;
+      if (level != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
 
-    levelData[coeff_ctr].level[0]=0;
-    if (level==0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].noLevels=1;
-    }
-    else if (level==0 && lowerInt==0)
-    {
-      levelData[coeff_ctr].level[1] = level+1;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
-    }
-    else if (level>0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
+        level  = isignab(level, *m7);
+
+        *m7 = level;
+        *DCL++ = level;
+        *DCR++ = run; 
+        // reset zero level counter
+        run    = 0;
+      nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
     }
     else
     {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].level[2] = level+1;
-      levelData[coeff_ctr].noLevels=3;
-      kStop=coeff_ctr;
-      kStart=coeff_ctr;
-      noCoeff++;
-    }
-
-    for (k=0; k<levelData[coeff_ctr].noLevels; k++)
-    {
-      err=(double)(levelData[coeff_ctr].level[k]<<q_bits)-(double)levelData[coeff_ctr].levelDouble;
-      levelData[coeff_ctr].errLevel[k]=(err*err*(double)estErr4x4[qp_rem][i][j])/normFact; 
-    }
+      run++;
+    }                    
   }
-  estBits=est_write_and_store_CBP_block_bit(currMB, LUMA_16AC, 0, 0);
-
-  est_writeRunLevel_CABAC(levelData, levelTrellis, LUMA_16AC, lambda_md, kStart, kStop, noCoeff, estBits);
-}
 
+  *DCL = 0;
 
+  return nonzero;
+}
 
+ 
diff --git a/lencod/src/quant8x8.c b/lencod/src/quant8x8.c
index d2cd78d..ee42805 100644
--- a/lencod/src/quant8x8.c
+++ b/lencod/src/quant8x8.c
@@ -28,7 +28,7 @@
 *
 ************************************************************************
 */
-void init_quant_8x8(ImageParameters *img)
+void init_quant_8x8(InputParameters *params, ImageParameters *img)
 {
   if (params->UseRDOQuant == 1)
   {
diff --git a/lencod/src/quant8x8_around.c b/lencod/src/quant8x8_around.c
index 7e7ff83..d913719 100644
--- a/lencod/src/quant8x8_around.c
+++ b/lencod/src/quant8x8_around.c
@@ -58,40 +58,45 @@ int quant_8x8_around(int (*tblock)[16], int block_y, int block_x, int  qp,
   int*  ACL = &ACLevel[0];
   int*  ACR = &ACRun[0];
 
-// Quantization
+  // Quantization
   for (coeff_ctr = 0; coeff_ctr < 64; coeff_ctr++)
   {
     i = *p_scan++;  // horizontal position
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-    if (level != 0)
+    if (*m7 != 0)
     {
-      if (params->symbol_mode == CAVLC && img->qp < 10)
-        level = imin(level, CAVLC_LEVEL_LIMIT);
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
 
-      fadjust8x8[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
+      if (level != 0)
+      {
+        fadjust8x8[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
 
-      nonzero = TRUE;
+        nonzero = TRUE;
 
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
 
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+      }
+      else
+      {
+        fadjust8x8[j][block_x + i] = 0;
+        run++;
+        *m7 = 0;
+      }
     }
     else
     {
       fadjust8x8[j][block_x + i] = 0;
       run++;
-      *m7 = 0;
-    }      
+    }
   }
 
   *ACL = 0;
@@ -144,33 +149,41 @@ int quant_8x8cavlc_around(int (*tblock)[16], int block_y, int block_x, int  qp,
       j = *p_scan++;  // vertical position
 
       m7 = &tblock[j][block_x + i];
-      scaled_coeff = iabs (*m7) * levelscale[j][i];
-      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-      if (level != 0)
+      if (*m7 != 0)
       {
-        if (params->symbol_mode == CAVLC && img->qp < 10)
-          level = imin(level, CAVLC_LEVEL_LIMIT);
-
-        fadjust8x8[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
-
-        nonzero=TRUE;
-
-        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[runs[k]];
-
-        level  = isignab(level, *m7);
-        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
-
-        *(ACL[k])++ = level;
-        *(ACR[k])++ = runs[k];
-        // reset zero level counter
-        runs[k] = 0;
+        scaled_coeff = iabs (*m7) * levelscale[j][i];
+        level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+        if (level != 0)
+        {
+          if (params->symbol_mode == CAVLC)
+            level = imin(level, CAVLC_LEVEL_LIMIT);
+
+          fadjust8x8[j][block_x + i] = rshift_rnd_sf((AdaptRndWeight * (scaled_coeff - (level << q_bits))), (q_bits + 1));
+
+          nonzero=TRUE;
+
+          *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[runs[k]];
+
+          level  = isignab(level, *m7);
+          *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
+
+          *(ACL[k])++ = level;
+          *(ACR[k])++ = runs[k];
+          // reset zero level counter
+          runs[k] = 0;
+        }
+        else
+        {
+          fadjust8x8[j][block_x + i] = 0;
+          runs[k]++;
+          *m7 = 0;      
+        }
       }
       else
       {
         fadjust8x8[j][block_x + i] = 0;
         runs[k]++;
-        *m7 = 0;      
       }
     }
   }
diff --git a/lencod/src/quant8x8_normal.c b/lencod/src/quant8x8_normal.c
index e06f193..8167eed 100644
--- a/lencod/src/quant8x8_normal.c
+++ b/lencod/src/quant8x8_normal.c
@@ -51,7 +51,7 @@ int quant_8x8_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
   static int scaled_coeff;
 
   int   level, run = 0;
-  int   nonzero = FALSE;  
+  int   nonzero = FALSE;
   int   qp_per = qp_per_matrix[qp];
   int   q_bits = Q_BITS_8 + qp_per;
   const byte *p_scan = &pos_scan[0][0];
@@ -65,27 +65,34 @@ int quant_8x8_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-    if (level != 0)
+    if (*m7 != 0)
     {
-      nonzero = TRUE;
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+      if (level != 0)
+      {
+        nonzero = TRUE;
 
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
 
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
     }
     else
     {
       run++;
-      *m7 = 0;
-    }      
+    }
   }
 
   *ACL = 0;
@@ -93,7 +100,6 @@ int quant_8x8_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
   return nonzero;
 }
 
-
 /*!
  ************************************************************************
  * \brief
@@ -139,6 +145,8 @@ int quant_8x8cavlc_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
       j = *p_scan++;  // vertical position
 
       m7 = &tblock[j][block_x + i];
+      if (*m7 != 0)
+      {
       scaled_coeff = iabs (*m7) * levelscale[j][i];
       level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
 
@@ -160,8 +168,13 @@ int quant_8x8cavlc_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
       }
       else
       {        
+          runs[k]++;
+          *m7 = 0;      
+        }
+      }
+      else
+      {
         runs[k]++;
-        *m7 = 0;      
       }
     }
   }
@@ -171,3 +184,4 @@ int quant_8x8cavlc_normal(int (*tblock)[16], int block_y, int block_x, int  qp,
 
   return nonzero;
 }
+
diff --git a/lencod/src/quant8x8_trellis.c b/lencod/src/quant8x8_trellis.c
index a2c3e95..9a154a7 100644
--- a/lencod/src/quant8x8_trellis.c
+++ b/lencod/src/quant8x8_trellis.c
@@ -92,7 +92,7 @@ const int estErr8x8[6][8][8]={
 };
 
 void rdoq_8x8(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem, 
-              int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[64]);
+              int **levelscale, int **leveloffset, const byte *p_scan, int levelTrellis[64]);
 /*!
  ************************************************************************
  * \brief
@@ -123,7 +123,7 @@ int quant_8x8_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
 
   int levelTrellis[64];
 
-  rdoq_8x8(tblock,block_y,block_x,qp_per,qp_rem,levelscale,leveloffset,pos_scan, levelTrellis);
+  rdoq_8x8(tblock,block_y,block_x,qp_per,qp_rem,levelscale,leveloffset,p_scan,levelTrellis);
 
   // Quantization
   for (coeff_ctr = 0; coeff_ctr < 64; coeff_ctr++)
@@ -132,34 +132,37 @@ int quant_8x8_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
     j = *p_scan++;  // vertical position
 
     m7 = &tblock[j][block_x + i];
-    /*
-    scaled_coeff = iabs (*m7) * levelscale[j][i];
-    level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-    */
-    level = levelTrellis[coeff_ctr];
-
-    if (level != 0)
-    {
-
-      if (params->symbol_mode == CAVLC && img->qp < 10)
-        level = imin(level, CAVLC_LEVEL_LIMIT);
+    if (*m7 != 0)
+    {    
+      /*
+      scaled_coeff = iabs (*m7) * levelscale[j][i];
+      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+      */
+      level = levelTrellis[coeff_ctr];
 
-      nonzero = TRUE;
+      if (level != 0)
+      {
+        nonzero = TRUE;
 
-      *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
+        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];
 
-      level  = isignab(level, *m7);
-      *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
-      *ACL++ = level;
-      *ACR++ = run; 
-      // reset zero level counter
-      run    = 0;
+        level  = isignab(level, *m7);
+        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
+        *ACL++ = level;
+        *ACR++ = run; 
+        // reset zero level counter
+        run    = 0;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }      
     }
     else
     {
       run++;
-      *m7 = 0;
-    }      
+    }
   }
 
   *ACL = 0;
@@ -212,27 +215,36 @@ int quant_8x8cavlc_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
       j = *p_scan++;  // vertical position
 
       m7 = &tblock[j][block_x + i];
-      scaled_coeff = iabs (*m7) * levelscale[j][i];
-      level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
-
-      if (level != 0)
+      if (*m7 != 0)
       {
-        nonzero=TRUE;
-
-        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[runs[k]];
-
-        level  = isignab(level, *m7);
-        *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
-
-        *(ACL[k])++ = level;
-        *(ACR[k])++ = runs[k];
-        // reset zero level counter
-        runs[k] = 0;
+        scaled_coeff = iabs (*m7) * levelscale[j][i];
+        level = (scaled_coeff + leveloffset[j][i]) >> q_bits;
+
+        if (level != 0)
+        {
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+          nonzero=TRUE;
+
+          *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[runs[k]];
+
+          level  = isignab(level, *m7);
+          *m7    = rshift_rnd_sf(((level * invlevelscale[j][i]) << qp_per), 6);
+
+          *(ACL[k])++ = level;
+          *(ACR[k])++ = runs[k];
+          // reset zero level counter
+          runs[k] = 0;
+        }
+        else
+        {        
+          runs[k]++;
+          *m7 = 0;      
+        }
       }
       else
-      {        
+      {
         runs[k]++;
-        *m7 = 0;      
       }
     }
   }
@@ -252,21 +264,13 @@ int quant_8x8cavlc_trellis(int (*tblock)[16], int block_y, int block_x, int  qp,
 ************************************************************************
 */
 void rdoq_8x8(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem, 
-              int **levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[64])
+              int **levelscale, int **leveloffset, const byte *p_scan, int levelTrellis[64])
 {
-  static int i,j, coeff_ctr;
-
-  static int *m7;
-
-  int level;
-
-  int q_bits = Q_BITS_8 + qp_per;
-
-  int m4[8][8], ii;
   levelDataStruct levelData[64];
-  double  lambda_md=0, normFact=pow(2,(2 * Q_BITS_8 + 9));
-  double err;
-  int lowerInt, kStart=0, kStop=0, noCoeff = 0;
+  double  lambda_md=0;
+  int kStart=0, kStop=0, noCoeff = 0;
+  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
+  int type = LUMA_8x8;
 
   if ((img->type==B_SLICE) && img->nal_reference_idc)
   {
@@ -277,61 +281,7 @@ void rdoq_8x8(int (*tblock)[16], int block_y, int block_x,int qp_per, int qp_rem
     lambda_md = img->lambda_md[img->type][img->masterQP]; 
   }
 
-  for (coeff_ctr = 0; coeff_ctr < 64; coeff_ctr++)
-  {
-    i = pos_scan[coeff_ctr][0];
-    j = pos_scan[coeff_ctr][1];
-
-    m7 = &tblock[j][block_x];
-    m4[j][i] = m7[i];
-  } 
-
-  for (coeff_ctr=0; coeff_ctr < 64; coeff_ctr++)
-  {
-    i=pos_scan[coeff_ctr][0];
-    j=pos_scan[coeff_ctr][1];
-
-    levelData[coeff_ctr].levelDouble = iabs(m4[j][i] * levelscale[i][j]);
-    level=(levelData[coeff_ctr].levelDouble>>q_bits);
-
-    lowerInt=(((int)levelData[coeff_ctr].levelDouble-(level<<q_bits))<(1<<(q_bits-1)))? 1 : 0;
-
-    levelData[coeff_ctr].level[0]=0;
-    if (level==0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].noLevels=1;
-    }
-    else if (level==0 && lowerInt==0)
-    {
-      levelData[coeff_ctr].level[1] = level+1;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
-    }
-    else if (level>0 && lowerInt==1)
-    {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].noLevels=2;
-      kStop=coeff_ctr;
-      noCoeff++;
-    }
-    else
-    {
-      levelData[coeff_ctr].level[1] = level;
-      levelData[coeff_ctr].level[2] = level+1;
-      levelData[coeff_ctr].noLevels=3;
-      kStop=coeff_ctr;
-      kStart=coeff_ctr;
-      noCoeff++;
-    }
-
-    for (ii=0; ii<levelData[coeff_ctr].noLevels; ii++)
-    {
-      err=(double)(levelData[coeff_ctr].level[ii]<<q_bits)-(double)levelData[coeff_ctr].levelDouble;
-      levelData[coeff_ctr].errLevel[ii] = (err * err * (double) estErr8x8[qp_rem][i][j]) / normFact; 
-    }
-  }
-
+  noCoeff = init_trellis_data(tblock, block_x, qp_per, qp_rem, levelscale, leveloffset, p_scan, currMB, levelData, &kStart, &kStop, type);
   est_writeRunLevel_CABAC(levelData, levelTrellis, LUMA_8x8, lambda_md, kStart, kStop, noCoeff, 0);
 }
 
diff --git a/lencod/src/quantChroma.c b/lencod/src/quantChroma.c
new file mode 100644
index 0000000..eeb4db7
--- /dev/null
+++ b/lencod/src/quantChroma.c
@@ -0,0 +1,57 @@
+
+/*!
+ *************************************************************************************
+ * \file quantChroma.c
+ *
+ * \brief
+ *    Quantization initialization function for Chroma blocks
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+#include "contributors.h"
+
+#include "global.h"
+#include "quant4x4.h"
+#include "quantChroma.h"
+
+/*!
+************************************************************************
+* \brief
+*    Quantization initialization function
+*
+************************************************************************
+*/
+void init_quant_Chroma(InputParameters *params, ImageParameters *img)
+{
+  if (params->UseRDOQuant == 1 && params->RDOQ_CR == 1)
+  {
+    quant_ac4x4cr = quant_ac4x4_trellis;
+    if (params->yuv_format == YUV422)
+      quant_dc_cr   = quant_dc4x2_trellis;
+    else
+      quant_dc_cr   = quant_dc2x2_trellis;
+  }
+  else if (params->UseRDOQuant == 1 || (!img->AdaptiveRounding))
+  {
+    quant_ac4x4cr = quant_ac4x4_normal;
+    if (params->yuv_format == YUV422)
+      quant_dc_cr   = quant_dc4x2_normal;
+    else
+      quant_dc_cr   = quant_dc2x2_normal;
+  }
+  else
+  {
+    quant_ac4x4cr = quant_ac4x4_around;
+    if (params->yuv_format == YUV422)
+      quant_dc_cr   = quant_dc4x2_around;
+    else
+      quant_dc_cr   = quant_dc2x2_around;
+  }
+}
+
+
diff --git a/lencod/src/quantChroma_around.c b/lencod/src/quantChroma_around.c
new file mode 100644
index 0000000..8541156
--- /dev/null
+++ b/lencod/src/quantChroma_around.c
@@ -0,0 +1,171 @@
+
+/*!
+ *************************************************************************************
+ * \file quantChroma_around.c
+ *
+ * \brief
+ *    Quantization process for a Chroma block
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+#include "contributors.h"
+
+#include <math.h>
+
+#include "global.h"
+#include "q_matrix.h"
+#include "quant4x4.h"
+#include "quantChroma.h"
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc2x2_around(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                       const byte (*pos_scan)[2])
+{
+  static int coeff_ctr;
+
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  //const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  m7 = *tblock;
+
+  // Quantization
+  for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
+  {
+    // we need to update leveloffset to a 4x1 array that would contain offset info for 
+    // every 2x2 DC position
+    if (*m7)
+    {
+      scaled_coeff = iabs (*m7) * levelscale;
+      level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        level = isignab(level, *m7);
+
+        *m7++ = ((level * invlevelscale) << qp_per) >> 5;
+
+        *DCL++ = level;
+        *DCR++ = run;
+        run    = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7++ = 0;
+      }
+    }
+    else
+    {
+      run++;
+      m7++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x2_around(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                       const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  // Quantization
+  for (coeff_ctr = 0; coeff_ctr < 8; coeff_ctr++)
+  {
+    j = *p_scan++;  // note that in this part, somehow coefficients were transposed from 2x4 to 4x2.
+    i = *p_scan++;  
+
+    m7 = &tblock[j][i];
+
+    if (*m7 != 0)
+    {
+      scaled_coeff = iabs (*m7) * levelscale;
+      level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+        level = isignab(level, *m7);
+
+        *m7 = rshift_rnd_sf(((level * invlevelscale) << qp_per), 6);
+
+        *DCL++ = level;
+        *DCR++ = run;
+        // reset zero level counter
+        run    = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
+    {
+      run++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+
+
diff --git a/lencod/src/quantChroma_normal.c b/lencod/src/quantChroma_normal.c
new file mode 100644
index 0000000..b5e8a3d
--- /dev/null
+++ b/lencod/src/quantChroma_normal.c
@@ -0,0 +1,171 @@
+
+/*!
+ *************************************************************************************
+ * \file quantChroma_normal.c
+ *
+ * \brief
+ *    Quantization process for a Chroma block
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+#include "contributors.h"
+
+#include <math.h>
+
+#include "global.h"
+#include "q_matrix.h"
+#include "quant4x4.h"
+#include "quantChroma.h"
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc2x2_normal(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset, 
+                       const byte (*pos_scan)[2])
+{
+  static int coeff_ctr;
+
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  //const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  m7 = *tblock;
+
+  // Quantization
+  for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
+  {
+    // we need to update leveloffset to a 4x1 array that would contain offset info for 
+    // every 2x2 DC position
+    if (*m7)
+    {
+      scaled_coeff = iabs (*m7) * levelscale;
+      level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        level = isignab(level, *m7);
+
+        *m7++ = ((level * invlevelscale) << qp_per) >> 5;
+
+        *DCL++ = level;
+        *DCR++ = run;
+        run    = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7++ = 0;
+      }
+    }
+    else
+    {
+      run++;
+      m7++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x2_normal(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                       const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+  static int scaled_coeff;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   q_bits = Q_BITS + qp_per + 1;
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  // Quantization
+  for (coeff_ctr = 0; coeff_ctr < 8; coeff_ctr++)
+  {
+    j = *p_scan++;  // note that in this part, somehow coefficients were transposed from 2x4 to 4x2.
+    i = *p_scan++;  
+
+    m7 = &tblock[j][i];
+
+    if (*m7 != 0)
+    {
+      scaled_coeff = iabs (*m7) * levelscale;
+      level = (scaled_coeff + (leveloffset[0][0] << 1) ) >> q_bits;
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+        level = isignab(level, *m7);
+
+        *m7 = rshift_rnd_sf(((level * invlevelscale) << qp_per), 6);
+
+        *DCL++ = level;
+        *DCR++ = run;
+        // reset zero level counter
+        run    = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
+    {
+      run++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+
+
diff --git a/lencod/src/quantChroma_trellis.c b/lencod/src/quantChroma_trellis.c
new file mode 100644
index 0000000..e2c388a
--- /dev/null
+++ b/lencod/src/quantChroma_trellis.c
@@ -0,0 +1,173 @@
+
+/*!
+ *************************************************************************************
+ * \file quantChroma_trellis.c
+ *
+ * \brief
+ *    Quantization process for a Chroma block (trellis based)
+ *
+ * \author
+ *    Main contributors (see contributors.h for copyright, address and affiliation details)
+ *    - Alexis Michael Tourapis                  <alexismt@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+#include "contributors.h"
+
+#include <math.h>
+
+#include "global.h"
+#include "q_matrix.h"
+#include "quant4x4.h"
+#include "quantChroma.h"
+#include "rdo_quant.h"
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc2x2_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                       const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   qp_rem = qp_rem_matrix[qp]; 
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  static int levelTrellis[16];
+
+  rdoq_dc(tblock,qp_per,qp_rem, levelscale, leveloffset,pos_scan, levelTrellis, CHROMA_DC);
+
+  for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
+  {
+    j = *p_scan++;  // note that in this part, coefficients were previously transposed from 2x4 to 4x2.
+    i = *p_scan++;  
+
+    m7 = &tblock[j][i];
+
+    if (*m7 != 0)
+    {
+      level = levelTrellis[coeff_ctr];
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+
+        level = isignab(level, *m7);
+
+        *m7 = ((level * invlevelscale) << qp_per) >> 5;
+
+        *DCL++  = level;
+        *DCR++  = run;
+        // reset zero level counter
+        run     = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
+    {
+      run++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Quantization process for All coefficients for a 2x2 DC block
+ *
+ * \par Input:
+ *
+ * \par Output:
+ *
+ ************************************************************************
+ */
+int quant_dc4x2_trellis(int (*tblock)[4], int qp, int* DCLevel, int* DCRun, 
+                       int **fadjust, int levelscale, int invlevelscale, int **leveloffset,
+                       const byte (*pos_scan)[2])
+{
+  static int i,j, coeff_ctr;
+
+  static int *m7;
+
+  int   level, run = 0;
+  int   nonzero = FALSE;  
+  int   qp_per = qp_per_matrix[qp];
+  int   qp_rem = qp_rem_matrix[qp]; 
+  const byte *p_scan = &pos_scan[0][0];
+  int*  DCL = &DCLevel[0];
+  int*  DCR = &DCRun[0];
+
+  static int levelTrellis[16];
+
+  rdoq_dc(tblock,qp_per,qp_rem, levelscale, leveloffset,pos_scan, levelTrellis, CHROMA_DC_2x4);
+
+  for (coeff_ctr=0; coeff_ctr < 4; coeff_ctr++)
+  {
+    j = *p_scan++;  // note that in this part, somehow coefficients were transposed from 2x4 to 4x2.
+    i = *p_scan++;  
+
+    m7 = &tblock[j][i];
+
+    if (*m7 != 0)
+    {
+      level = levelTrellis[coeff_ctr];
+
+      if (level  != 0)
+      {
+        if (params->symbol_mode == CAVLC)
+          level = imin(level, CAVLC_LEVEL_LIMIT);
+        level = isignab(level, *m7);
+
+        *m7 = rshift_rnd_sf(((level * invlevelscale) << qp_per), 6);
+
+        *DCL++  = level;
+        *DCR++  = run;
+        // reset zero level counter
+        run     = 0;
+        nonzero = TRUE;
+      }
+      else
+      {
+        run++;
+        *m7 = 0;
+      }
+    }
+    else
+    {
+      run++;
+    }
+  }
+
+  *DCL = 0;
+
+  return nonzero;
+}
+
+
diff --git a/lencod/src/ratectl.c b/lencod/src/ratectl.c
index 6134a26..a06d534 100644
--- a/lencod/src/ratectl.c
+++ b/lencod/src/ratectl.c
@@ -57,7 +57,7 @@ void update_qp_cbp(Macroblock *currMB, short best_mode)
     currMB->delta_qp = 0;
     currMB->qp       = currMB->prev_qp;
     img->qp          = currMB->qp;
-    update_qp(currMB);    
+    update_qp(img, currMB);    
 
   }
 
@@ -67,9 +67,6 @@ void update_qp_cbp(Macroblock *currMB, short best_mode)
     rdopt->qp        = currMB->qp;
     rdopt->delta_qp  = currMB->delta_qp;
     rdopt->prev_cbp  = currMB->prev_cbp;
-
-    delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-    qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
   }  
 }
 
@@ -404,7 +401,7 @@ void update_qp_cbp_tmp(Macroblock *currMB, int cbp, int best_mode)
     currMB->delta_qp  = 0;
     currMB->qp        = currMB->prev_qp;
     img->qp           = currMB->qp;
-    update_qp(currMB);        
+    update_qp(img, currMB);        
   }
 }
 
diff --git a/lencod/src/rc_quadratic.c b/lencod/src/rc_quadratic.c
index 7ccb9fe..2109d29 100644
--- a/lencod/src/rc_quadratic.c
+++ b/lencod/src/rc_quadratic.c
@@ -604,9 +604,12 @@ void rc_init_pict(rc_quadratic *prc, int fieldpic,int topfield,int targetcomputa
       /* update the total number of bits if the bandwidth is changed*/
       if(prc->PrevBitRate != prc->bit_rate)
         generic_RC->RemainingBits +=(int) floor((prc->bit_rate-prc->PrevBitRate) * (prc->Np + prc->Nb) / prc->frame_rate+0.5);
-      if((prc->NumberofCodedPFrame==1)&&(generic_RC->NumberofCodedBFrame==1))
+      if(generic_RC->NumberofCodedBFrame == 1)
       {
-        prc->AveWp = prc->Wp;
+        if(prc->NumberofCodedPFrame == 1)
+        {
+          prc->AveWp = prc->Wp;
+        }
         prc->AveWb = prc->Wb;
       }
       else if(generic_RC->NumberofCodedBFrame > 1)
@@ -681,9 +684,6 @@ void rc_init_pict(rc_quadratic *prc, int fieldpic,int topfield,int targetcomputa
       }
       prc->Target = (int)(mult * prc->Target);
 
-      /* reserve some bits for smoothing */
-      prc->Target = (int)((1.0 - 0.0 * params->successive_Bframe) * prc->Target);
-
       /* HRD consideration */
       if ( params->RCUpdateMode != RC_MODE_3 || img->type == P_SLICE )
         prc->Target = iClip3(prc->LowerBound, prc->UpperBound2, prc->Target);
@@ -2458,9 +2458,9 @@ void updateModelQPFrame( rc_quadratic *prc, int m_Bits )
  *    rate control at the MB level
  *************************************************************************************
 */
-void rc_handle_mb( int prev_mb, Macroblock *currMB, Slice *curr_slice )
+int rc_handle_mb( int prev_mb, Macroblock *currMB, Slice *curr_slice )
 {
-  int  dq;
+  int  mb_qp = img->qp;
   Macroblock *prevMB = NULL;
 
   if (prev_mb > -1)
@@ -2468,154 +2468,66 @@ void rc_handle_mb( int prev_mb, Macroblock *currMB, Slice *curr_slice )
     prevMB = &img->mb_data[prev_mb];
 
     if ( params->MbInterlace == ADAPTIVE_CODING && !img->bot_MB && currMB->mb_field )
-      currMB->qp = img->qp = prevMB->qp;
-    currMB->prev_qp = prevMB->qp;
-
-    currMB->prev_dqp = (prevMB->slice_nr == img->current_slice_nr) ? prevMB->delta_qp : 0;
-  }
-  else
-  {
-    currMB->prev_qp  = curr_slice->qp;
-    currMB->prev_dqp = 0;
+      mb_qp = prevMB->qp;
   }
+
   // frame layer rate control
-  if (params->basicunit == img->FrameSizeInMbs)
-  {
-     currMB->qp       = img->qp;
-     currMB->delta_qp = currMB->qp - currMB->prev_qp;    
-  }
-  else   // basic unit layer rate control
+  if (params->basicunit != img->FrameSizeInMbs)
   {
     // each I or B frame has only one QP
     if ( ((img->type == I_SLICE || img->type == B_SLICE) && params->RCUpdateMode != RC_MODE_1 ) || !(img->number) )
     {
-     currMB->qp       = img->qp;
-     currMB->delta_qp = currMB->qp - currMB->prev_qp;    
+      return mb_qp;
     }
     else if ( img->type == P_SLICE || params->RCUpdateMode == RC_MODE_1 )
     {
       if (!img->write_macroblock) //write macroblock
       {
-        if (prev_mb < 0) //first macroblock (of slice)
-        {
-          // Initialize delta qp change from last macroblock. Feature may be used for future rate control
-          currMB->qp       = img->qp;
-          currMB->delta_qp = currMB->qp - currMB->prev_qp;    
-          delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-          qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
-        }
-        else
+        if (prev_mb > -1) 
         {      
           if (!((params->MbInterlace) && img->bot_MB)) //top macroblock
           {
-            prevMB = &img->mb_data[prev_mb];
-            if (prevMB->prev_cbp == 1)
-            {
-              currMB->qp       = img->qp;
-              currMB->delta_qp = currMB->qp - prevMB->qp; 
-            }
-            else
+            if (prevMB->prev_cbp != 1)
             {
-              currMB->qp = img->qp = prevMB->prev_qp;
-              currMB->delta_qp = currMB->qp - prevMB->qp;
+              mb_qp = prevMB->prev_qp;
             }
-            delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-            qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
-          }
-          else //bottom macroblock
-          {
-            // Initialize delta qp change from last macroblock. Feature may be used for future rate control
-            currMB->qp       = img->qp;
-            currMB->delta_qp = currMB->qp - currMB->prev_qp;    
           }
         }
       }
-      else
-      {
-        if (!img->bot_MB) //write top macroblock
-        {
-          if (img->write_mbaff_frame)
-          {
-            currMB->delta_qp = delta_qp_mbaff[0][img->bot_MB];
-            currMB->qp = img->qp =   qp_mbaff[0][img->bot_MB];
-          }
-          else
-          {
-            if (prev_mb < 0) //first macroblock (of slice)
-            {
-              // Initialize delta qp change from last macroblock. Feature may be used for future rate control
-              currMB->qp       = img->qp;
-              currMB->delta_qp = currMB->qp - currMB->prev_qp;    
-              delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-              qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
-            }
-            else
-            {
-              currMB->delta_qp = delta_qp_mbaff[1][img->bot_MB];
-              currMB->qp = img->qp =   qp_mbaff[1][img->bot_MB];
-            }
-          }
-        }
-        else //write bottom macroblock
-        {
-            currMB->qp       = img->qp;
-            currMB->delta_qp = currMB->qp - currMB->prev_qp;    
-        }
-      }
 
       // compute the quantization parameter for each basic unit of P frame
-      
+
       if (!img->write_macroblock)
       {
-
         if(!((params->MbInterlace) && img->bot_MB))
         {
           if(params->RCUpdateMode <= MAX_RC_MODE && (img->NumberofCodedMacroBlocks > 0) && (img->NumberofCodedMacroBlocks % img->BasicUnit == 0))
           {
+            updateRCModel(quadratic_RC);
             // frame coding
             if(active_sps->frame_mbs_only_flag)
             {
-              updateRCModel(quadratic_RC);
-              img->BasicUnitQP=updateQP(quadratic_RC, generic_RC->TopFieldFlag);
-            }
-            // picture adaptive field/frame coding
-            else if((params->PicInterlace!=FRAME_CODING)&&(!params->MbInterlace)&&(generic_RC->NoGranularFieldRC==0))
-            {
-              updateRCModel(quadratic_RC);
               img->BasicUnitQP = updateQP(quadratic_RC, generic_RC->TopFieldFlag);
+
             }
-            // mb adaptive f/f coding, field coding
-            else if((params->MbInterlace))
+            // picture adaptive field/frame coding
+            else if(params->MbInterlace || ((params->PicInterlace!=FRAME_CODING) && (generic_RC->NoGranularFieldRC==0)))
             {
-              updateRCModel(quadratic_RC);
               img->BasicUnitQP = updateQP(quadratic_RC, generic_RC->TopFieldFlag);
             }
           }
 
           if(img->current_mb_nr==0)
-            img->BasicUnitQP=img->qp;
-          currMB->predict_qp = iClip3(currMB->qp - img->min_qp_delta, currMB->qp + img->max_qp_delta, img->BasicUnitQP);
+            img->BasicUnitQP = mb_qp;
 
-          dq = currMB->delta_qp + currMB->predict_qp - currMB->qp;          
-          dq = iClip3(-img->min_qp_delta, img->max_qp_delta, dq);
-          currMB->predict_error = dq - currMB->delta_qp;
-          img->qp   += currMB->predict_error; 
-          currMB->qp =  img->qp;
-          currMB->delta_qp = dq;          
 
-          if (params->MbInterlace)
-          {
-            delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-            qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
-          }          
+          mb_qp = img->BasicUnitQP;
+          mb_qp = iClip3(-img->bitdepth_luma_qp_scale, 51, mb_qp);
         }
-        else
-          currMB->prev_qp = img->qp;
       }
     }
   }
-
-  update_qp(currMB);
+  return mb_qp;
 }
 
 /*!
@@ -2730,15 +2642,15 @@ void rc_free_memory( void )
 void rc_update_mb_stats( Macroblock *currMB, int *bitCount )
 {
   // Rate control
-  img->NumberofMBHeaderBits= bitCount[BITS_MB_MODE] + bitCount[BITS_INTER_MB]
-                           + bitCount[BITS_CBP_MB ] + bitCount[BITS_DELTA_QUANT_MB];
-  img->NumberofMBTextureBits= bitCount[BITS_COEFF_Y_MB]+ bitCount[BITS_COEFF_UV_MB];
+  img->NumberofMBHeaderBits = bitCount[BITS_MB_MODE] + bitCount[BITS_INTER_MB]
+                            + bitCount[BITS_CBP_MB ] + bitCount[BITS_DELTA_QUANT_MB];
+  img->NumberofMBTextureBits = bitCount[BITS_COEFF_Y_MB]+ bitCount[BITS_COEFF_UV_MB];
 
   switch (params->RCUpdateMode)
   {
   case RC_MODE_0:  case RC_MODE_1:  case RC_MODE_2:  case RC_MODE_3:
-    generic_RC->NumberofTextureBits +=img->NumberofMBTextureBits;
-    generic_RC->NumberofHeaderBits +=img->NumberofMBHeaderBits;
+    generic_RC->NumberofTextureBits += img->NumberofMBTextureBits;
+    generic_RC->NumberofHeaderBits  += img->NumberofMBHeaderBits;
     // basic unit layer rate control
     if(img->BasicUnit < img->FrameSizeInMbs)
     {
diff --git a/lencod/src/rd_intra_jm.c b/lencod/src/rd_intra_jm.c
index 3c215b0..ce114a1 100644
--- a/lencod/src/rd_intra_jm.c
+++ b/lencod/src/rd_intra_jm.c
@@ -15,28 +15,18 @@
  **************************************************************************
  */
 
-#include <math.h>
 #include <limits.h>
 
 #include "global.h"
 
-#include "rdopt_coding_state.h"
-#include "memalloc.h"
-#include "mb_access.h"
-#include "elements.h"
-#include "intrarefresh.h"
 #include "image.h"
-#include "transform8x8.h"
-#include "cabac.h"
-#include "vlc.h"
-#include "ratectl.h"            // head file for rate control
-#include "mode_decision.h"
 #include "macroblock.h"
-#include "symbol.h"
-#include "q_offsets.h"
+#include "mb_access.h"
+#include "rdopt_coding_state.h"
+#include "mode_decision.h"
 #include "rdopt.h"
 #include "rd_intra_jm.h"
-
+#include "q_around.h"
 
 /*!
  *************************************************************************************
@@ -46,10 +36,10 @@
  */
 int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int  b4,  double  lambda,  double*  min_cost, int cr_cbp[3])
 {
-  int     ipmode, best_ipmode = 0, i, j, y, dummy;
-  int     c_nz, nonzero = 0;
-  int*    ACLevel = img->cofAC[b8][b4][0];
-  int*    ACRun   = img->cofAC[b8][b4][1];
+  int    ipmode, best_ipmode = 0, i, j, y, dummy;
+  int    c_nz, nonzero = 0;
+  int*   ACLevel = img->cofAC[b8][b4][0];
+  int*   ACRun   = img->cofAC[b8][b4][1];
   int    c_nzCbCr[3]= {999,999, 999};
   static imgpel  rec4x4[4][4];
   static imgpel  rec4x4CbCr[2][4][4];
@@ -66,7 +56,7 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
   int    pic_block_y = pic_pix_y >> 2;
   double min_rdcost  = 1e30;
 
-  int left_available, up_available, all_available;  
+  int left_available, up_available, all_available;
 
   char   upMode;
   char   leftMode;
@@ -131,15 +121,15 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
     if( available_mode)
     {
       // get prediction and prediction error
-      generate_pred_error(&pCurImg[pic_opix_y], img->mpr_4x4[0][ipmode], &img->mpr[0][block_y], &img->m7[0][block_y], pic_opix_x, block_x);     
+      generate_pred_error(&pCurImg[pic_opix_y], img->mpr_4x4[0][ipmode], &img->mb_pred[0][block_y], &img->mb_ores[0][block_y], pic_opix_x, block_x);     
 
       if (img->yuv_format == YUV444)
       {
-        ipmode_DPCM=ipmode;
+        ipmode_DPCM = ipmode;
         if (!IS_INDEPENDENT(params)) 
         {
-          generate_pred_error(&imgUV_org[0][pic_opix_y], img->mpr_4x4[1][ipmode], &img->mpr[1][block_y], &img->m7[1][block_y], pic_opix_x, block_x);
-          generate_pred_error(&imgUV_org[1][pic_opix_y], img->mpr_4x4[2][ipmode], &img->mpr[2][block_y], &img->m7[2][block_y], pic_opix_x, block_x);     
+          generate_pred_error(&pImgOrg[1][pic_opix_y], img->mpr_4x4[1][ipmode], &img->mb_pred[1][block_y], &img->mb_ores[1][block_y], pic_opix_x, block_x);
+          generate_pred_error(&pImgOrg[2][pic_opix_y], img->mpr_4x4[2][ipmode], &img->mb_pred[2][block_y], &img->mb_ores[2][block_y], pic_opix_x, block_x);     
         }
       }
 
@@ -153,7 +143,7 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
       {
         //--- set coefficients ---
         memcpy(cofAC4x4[0],ACLevel, 18 * sizeof(int));
-        memcpy(cofAC4x4[1],ACRun, 18 * sizeof(int));
+        memcpy(cofAC4x4[1],ACRun,   18 * sizeof(int));
 
         //--- set reconstruction ---
         for (y=0; y<4; y++)
@@ -200,7 +190,7 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
         //store_coding_state (currMB, cs_ib4);
         if (img->AdaptiveRounding)
         {
-          store_adaptive_rounding (block_y, block_x);
+          store_adaptive_rounding (img, block_y, block_x);
         }
 
       }
@@ -229,8 +219,8 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
       {
         for (i=0; i<4; i++)
         {
-          img->mpr[k][block_y+j][block_x+i]  = img->mpr_4x4[k][best_ipmode][j][i];
-          img->m7[k][block_y+j][block_x+i]   = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_4x4[k][best_ipmode][j][i];
+          img->mb_pred[k][block_y+j][block_x+i]  = img->mpr_4x4[k][best_ipmode][j][i];
+          img->mb_ores[k][block_y+j][block_x+i]   = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_4x4[k][best_ipmode][j][i];
         }
       }
       cr_cbp[k] = pDCT_4x4(currMB, k, block_x,block_y,&dummy,1);
@@ -245,7 +235,7 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
   for (y=0; y<BLOCK_SIZE; y++)
   {
     memcpy (&enc_picture->imgY[pic_pix_y + y][pic_pix_x],rec4x4[y],    BLOCK_SIZE * sizeof(imgpel));
-    memcpy (&img->mpr[0][block_y + y][block_x],img->mpr_4x4[0][best_ipmode][y], BLOCK_SIZE * sizeof(imgpel));
+    memcpy (&img->mb_pred[0][block_y + y][block_x],img->mpr_4x4[0][best_ipmode][y], BLOCK_SIZE * sizeof(imgpel));
   }
 
   // SP/SI reconstuction
@@ -253,7 +243,7 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
   {
     for (y=0; y<BLOCK_SIZE; y++)
     {
-      memcpy (&lrec[pic_pix_y+y][pic_pix_x],lrec4x4[y], BLOCK_SIZE * sizeof(int));//restore coefficients when encoding primary SP frame
+      memcpy (&lrec[pic_pix_y+y][pic_pix_x], lrec4x4[y], BLOCK_SIZE * sizeof(int));//restore coefficients when encoding primary SP frame
     }
   }
   if (img->P444_joined) 
@@ -267,14 +257,14 @@ int Mode_Decision_for_4x4IntraBlocks_JM_High (Macroblock *currMB, int  b8,  int
       for (y=0; y<BLOCK_SIZE; y++)
       {
         memcpy(&enc_picture->imgUV[uv][pic_pix_y+y][pic_pix_x],rec4x4CbCr[uv][y], BLOCK_SIZE * sizeof(imgpel));
-        memcpy(&img->mpr[uv + 1][block_y+y][block_x], img->mpr_4x4[uv + 1][best_ipmode][y], BLOCK_SIZE * sizeof(imgpel));
+        memcpy(&img->mb_pred[uv + 1][block_y+y][block_x], img->mpr_4x4[uv + 1][best_ipmode][y], BLOCK_SIZE * sizeof(imgpel));
       } 
     }
   }
 
   if (img->AdaptiveRounding)
   {
-    update_adaptive_rounding(block_y, block_x);
+    update_adaptive_rounding(img, block_y, block_x);
   }
 
 
@@ -371,8 +361,8 @@ int Mode_Decision_for_4x4IntraBlocks_JM_Low (Macroblock *currMB, int  b8,  int
 
       if (img->P444_joined)
       {
-        compute_comp_cost(&imgUV_org[0][pic_opix_y], img->mpr_4x4[1][ipmode], pic_opix_x, &cost);
-        compute_comp_cost(&imgUV_org[1][pic_opix_y], img->mpr_4x4[2][ipmode], pic_opix_x, &cost);
+        compute_comp_cost(&pImgOrg[1][pic_opix_y], img->mpr_4x4[1][ipmode], pic_opix_x, &cost);
+        compute_comp_cost(&pImgOrg[2][pic_opix_y], img->mpr_4x4[2][ipmode], pic_opix_x, &cost);
       }
       
       if (cost < *min_cost)
@@ -394,11 +384,11 @@ int Mode_Decision_for_4x4IntraBlocks_JM_Low (Macroblock *currMB, int  b8,  int
     (char) (mostProbableMode == best_ipmode ? -1 : (best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1));
 
   // get prediction and prediction error
-  generate_pred_error(&pCurImg[pic_opix_y], img->mpr_4x4[0][best_ipmode], &img->mpr[0][block_y], &img->m7[0][block_y], pic_opix_x, block_x);
+  generate_pred_error(&pCurImg[pic_opix_y], img->mpr_4x4[0][best_ipmode], &img->mb_pred[0][block_y], &img->mb_ores[0][block_y], pic_opix_x, block_x);
 
   ipmode_DPCM=best_ipmode;  
 
-  select_dct(currMB);
+  select_dct(img, currMB);
   nonzero = cr_cbp[0] = pDCT_4x4 (currMB, PLANE_Y, block_x, block_y, &dummy, 1);
 
   if (img->P444_joined)
@@ -411,8 +401,8 @@ int Mode_Decision_for_4x4IntraBlocks_JM_Low (Macroblock *currMB, int  b8,  int
       {
         for (i=0; i<4; i++)
         {
-          img->mpr[k][block_y+j][block_x+i]  = img->mpr_4x4[k][best_ipmode][j][i];    
-          img->m7[k][block_y+j][block_x+i]   = pImgOrg[k][pic_opix_y+j][pic_opix_x+i] - img->mpr_4x4[k][best_ipmode][j][i]; 
+          img->mb_pred[k][block_y+j][block_x+i] = img->mpr_4x4[k][best_ipmode][j][i];    
+          img->mb_ores[k][block_y+j][block_x+i] = pImgOrg[k][pic_opix_y+j][pic_opix_x+i] - img->mpr_4x4[k][best_ipmode][j][i]; 
         }
       }
 
@@ -509,6 +499,7 @@ void Intra16x16_Mode_Decision (Macroblock* currMB, int* i16mode)
 {
   /* generate intra prediction samples for all 4 16x16 modes */
   intrapred_16x16 (currMB, PLANE_Y);
+  
   if (img->P444_joined)
   {
     select_plane(PLANE_U);
diff --git a/lencod/src/rdo_quant.c b/lencod/src/rdo_quant.c
index 014a9ce..162da7a 100644
--- a/lencod/src/rdo_quant.c
+++ b/lencod/src/rdo_quant.c
@@ -39,7 +39,8 @@ const int entropyBits[128]=
   151031, 153495, 155959, 158423, 160887, 163351, 165814, 168278, 
   170742, 173207, 175669, 178134, 180598, 183061, 185525, 187989
 };
-
+extern const int estErr4x4[6][4][4];
+extern const int estErr8x8[6][8][8]; 
 extern const int maxpos       [];
 extern const int type2ctx_bcbp[];
 extern const int type2ctx_map [];
@@ -289,6 +290,195 @@ int biari_state(EncodingEnvironmentPtr eep, signed short symbol, BiContextTypePt
   return(ctx_state);
 }
 
+/*!
+************************************************************************
+* \brief
+*    Rate distortion optimized Quantization process for 
+*    all coefficients in a DC block (luma, chroma)
+*
+************************************************************************
+*/
+void rdoq_dc(int (*tblock)[4], int qp_per, int qp_rem, int levelscale, int **leveloffset, const byte (*pos_scan)[2], int levelTrellis[], int type)
+{
+  const byte *p_scan = &pos_scan[0][0];
+  levelDataStruct levelData[16];
+  double  lambda_md = 0;
+  int kStart=0, kStop=0, noCoeff = 0, estBits;
+  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
+
+  if ((img->type==B_SLICE) && img->nal_reference_idc)
+  {
+    lambda_md = img->lambda_md[5][img->masterQP];  
+  }
+  else
+  {
+    lambda_md = img->lambda_md[img->type][img->masterQP]; 
+  }
+
+  noCoeff = init_trellis_data_DC(tblock, qp_per, qp_rem, levelscale, leveloffset, p_scan, currMB, levelData, &kStart, &kStop, type);
+  estBits = est_write_and_store_CBP_block_bit(currMB, type);
+  est_writeRunLevel_CABAC(levelData, levelTrellis, type, lambda_md, kStart, kStop, noCoeff, estBits);
+}
+
+
+
+/*!
+****************************************************************************
+* \brief
+*    estimate CABAC CBP bits
+****************************************************************************
+*/
+int init_trellis_data(int (*tblock)[16], int block_x, int qp_per, int qp_rem, int **levelscale, int **leveloffset, const byte *p_scan, Macroblock *currMB,  
+                      levelDataStruct levelData[], int* kStart, int* kStop, int type)
+{
+  int noCoeff = 0;
+  int i, j, coeff_ctr, end_coeff_ctr = ( (type == LUMA_8x8) ? 64 : ( (type == LUMA_4x4 || type == CHROMA_AC) ? 16 : 15 ) );
+  static int *m7;
+  int q_bits;
+  double err, normFact;
+  int level, lowerInt, k;
+
+  if (type == LUMA_8x8)
+  {
+    q_bits = Q_BITS_8 + qp_per;
+    normFact = pow(2,(2 * Q_BITS_8 + 9));
+  }
+  else
+  {
+    q_bits = Q_BITS + qp_per; 
+    normFact = pow(2,(2 * DQ_BITS + 19)); 
+  }
+
+  for (coeff_ctr = 0; coeff_ctr < end_coeff_ctr; coeff_ctr++)
+  {
+    i = *p_scan++;  // horizontal position
+    j = *p_scan++;  // vertical position
+    m7 = &tblock[j][block_x + i];
+
+    levelData[coeff_ctr].levelDouble = iabs(*m7 * levelscale[i][j]);
+    level = (levelData[coeff_ctr].levelDouble >> q_bits);
+
+    lowerInt=( ((int)levelData[coeff_ctr].levelDouble - (level<<q_bits)) < ( 1 << (q_bits - 1) ) )? 1 : 0;
+    levelData[coeff_ctr].level[0] = 0;
+
+    if (level == 0 && lowerInt == 1)
+    {
+      levelData[coeff_ctr].noLevels = 1;
+    }
+    else if (level == 0 && lowerInt == 0)
+    {
+      levelData[coeff_ctr].level[1] = level + 1;
+      levelData[coeff_ctr].noLevels = 2;
+      *kStop = coeff_ctr;
+      noCoeff++;
+    }
+    else if (level > 0 && lowerInt == 1)
+    {
+      levelData[coeff_ctr].level[1] = level;
+      levelData[coeff_ctr].noLevels = 2;
+      *kStop = coeff_ctr;
+      noCoeff++;
+    }
+    else
+    {
+      levelData[coeff_ctr].level[1] = level;
+      levelData[coeff_ctr].level[2] = level + 1;
+      levelData[coeff_ctr].noLevels = 3;
+      *kStop = coeff_ctr;
+      *kStart = coeff_ctr;
+      noCoeff++;
+    }
+
+    for (k = 0; k < levelData[coeff_ctr].noLevels; k++)
+    {
+      err = (double)(levelData[coeff_ctr].level[k]<<q_bits)-(double)levelData[coeff_ctr].levelDouble;
+      if (type == LUMA_8x8)
+        levelData[coeff_ctr].errLevel[k] = (err*err*(double)estErr8x8[qp_rem][i][j])/normFact; 
+      else
+        levelData[coeff_ctr].errLevel[k] = (err*err*(double)estErr4x4[qp_rem][i][j])/normFact; 
+    }
+  }
+  return (noCoeff);
+}
+
+
+/*!
+****************************************************************************
+* \brief
+*    estimate CABAC CBP bits for Luma DC
+****************************************************************************
+*/
+int init_trellis_data_DC(int (*tblock)[4], int qp_per, int qp_rem, 
+                         int levelscale, int **leveloffset, const byte *p_scan, Macroblock *currMB,  
+                         levelDataStruct levelData[], int* kStart, int* kStop, int type)
+{
+  int noCoeff = 0;
+  int i, j, coeff_ctr, end_coeff_ctr;
+  static int *m7;
+  int q_bits;
+  double err, normFact;
+  int level, lowerInt, k;
+
+  end_coeff_ctr = ( (type == LUMA_16DC || type == CB_16DC || type == CB_16DC || type == CHROMA_DC_4x4) ? 16 : ( (type == CHROMA_DC) ? 4 : 8 ) );
+  q_bits = Q_BITS + qp_per + 1; 
+  normFact = pow(2,(2 * DQ_BITS + 19)); 
+
+  for (coeff_ctr = 0; coeff_ctr < end_coeff_ctr; coeff_ctr++)
+  {
+    if (type == LUMA_16DC)
+    {
+      i = *p_scan++;  // horizontal position
+      j = *p_scan++;  // vertical position
+    }
+    else
+    {
+      j = *p_scan++;  // horizontal position
+      i = *p_scan++;  // vertical position
+    }
+    m7 = &tblock[j][i];
+
+    levelData[coeff_ctr].levelDouble = iabs(*m7 * levelscale);
+    level = (levelData[coeff_ctr].levelDouble >> q_bits);
+
+    lowerInt=( ((int)levelData[coeff_ctr].levelDouble - (level<<q_bits)) < ( 1 << (q_bits - 1) ) )? 1 : 0;
+    levelData[coeff_ctr].level[0] = 0;
+    if (level == 0 && lowerInt == 1)
+    {
+      levelData[coeff_ctr].noLevels = 1;
+    }
+    else if (level == 0 && lowerInt == 0)
+    {
+      levelData[coeff_ctr].level[1] = level + 1;
+      levelData[coeff_ctr].noLevels = 2;
+      *kStop = coeff_ctr;
+      noCoeff++;
+    }
+    else if (level > 0 && lowerInt == 1)
+    {
+      levelData[coeff_ctr].level[1] = level;
+      levelData[coeff_ctr].noLevels = 2;
+      *kStop = coeff_ctr;
+      noCoeff++;
+    }
+    else
+    {
+      levelData[coeff_ctr].level[1] = level;
+      levelData[coeff_ctr].level[2] = level + 1;
+      levelData[coeff_ctr].noLevels = 3;
+      *kStop = coeff_ctr;
+      *kStart = coeff_ctr;
+      noCoeff++;
+    }
+
+    for (k = 0; k < levelData[coeff_ctr].noLevels; k++)
+    {
+      err = (double)(levelData[coeff_ctr].level[k]<<q_bits)-(double)levelData[coeff_ctr].levelDouble;
+      levelData[coeff_ctr].errLevel[k] = (err*err*(double)estErr4x4[qp_rem][0][0])/normFact; 
+    }
+  }
+  return (noCoeff);
+}
+
 
 /*!
 ****************************************************************************
@@ -296,61 +486,142 @@ int biari_state(EncodingEnvironmentPtr eep, signed short symbol, BiContextTypePt
 *    estimate CABAC CBP bits
 ****************************************************************************
 */
-int est_write_and_store_CBP_block_bit(Macroblock* currMB, int type, int block_y, int block_x) // marta - CBP
+/*!
+****************************************************************************
+* \brief
+*    estimate CABAC CBP bits
+****************************************************************************
+*/
+int est_write_and_store_CBP_block_bit(Macroblock* currMB, int type) 
 {
 #define BIT_SET(x,n)  ((int)(((x)&((int64)1<<(n)))>>(n)))
 
-  int bit, default_bit = (IS_INTRA(currMB) ? 1 : 0);
+  int y_ac        = (type==LUMA_16AC || type==LUMA_8x8 || type==LUMA_8x4 || type==LUMA_4x8 || type==LUMA_4x4
+    || type==CB_16AC || type==CB_8x8 || type==CB_8x4 || type==CB_4x8 || type==CB_4x4
+    || type==CR_16AC || type==CR_8x8 || type==CR_8x4 || type==CR_4x8 || type==CR_4x4);
+  int y_dc        = (type==LUMA_16DC || type==CB_16DC || type==CR_16DC); 
+  int u_ac        = (type==CHROMA_AC && !img->is_v_block);
+  int v_ac        = (type==CHROMA_AC &&  img->is_v_block);
+  int chroma_dc   = (type==CHROMA_DC || type==CHROMA_DC_2x4 || type==CHROMA_DC_4x4);
+  int u_dc        = (chroma_dc && !img->is_v_block);
+  int v_dc        = (chroma_dc &&  img->is_v_block);
+  int j           = ((y_ac || u_ac || v_ac ? img->subblock_y : 0) << 2);
+  int i           =  (y_ac || u_ac || v_ac ? img->subblock_x : 0);
+  int bit;
+  int default_bit =  (IS_INTRA(currMB) ? 1 : 0);
   int upper_bit   = default_bit;
   int left_bit    = default_bit;
-  int ctx, estBits;
+  int ctx, estBits = 0;
 
   int bit_pos_a   = 0;
   int bit_pos_b   = 0;
-  int *mb_size = img->mb_size[IS_LUMA];
 
-  if (type!=LUMA_8x8)
+  PixelPos block_a, block_b;
+
+  if (y_ac || y_dc)
   {
-    PixelPos block_a, block_b;
+    get4x4Neighbour(currMB, (i << 2) - 1, j   , img->mb_size[IS_LUMA], &block_a);
+    get4x4Neighbour(currMB, (i << 2),     j -1, img->mb_size[IS_LUMA], &block_b);
+    if (y_ac)
+    {
+      if (block_a.available)
+        bit_pos_a = 4*block_a.y + block_a.x;
+      if (block_b.available)
+        bit_pos_b = 4*block_b.y + block_b.x;
+    }
+  }
+  else
+  {
+    get4x4Neighbour(currMB, (i << 2) - 1, j    , img->mb_size[IS_CHROMA], &block_a);
+    get4x4Neighbour(currMB, (i << 2),     j - 1, img->mb_size[IS_CHROMA], &block_b);
+    if (u_ac||v_ac)
+    {
+      if (block_a.available)
+        bit_pos_a = (block_a.y << 2) + block_a.x;
+      if (block_b.available)
+        bit_pos_b = (block_b.y << 2) + block_b.x;
+    }
+  }
 
-    get4x4Neighbour (currMB, block_x - 1 , block_y    , mb_size, &block_a);    
-    get4x4Neighbour (currMB, block_x     , block_y - 1, mb_size, &block_b);    
+  bit = (y_dc ? 0 : y_ac ? 1 : u_dc ? 17 : v_dc ? 18 : u_ac ? 19 : 35);
 
-    if (block_a.available)
-      bit_pos_a = 4*block_a.y + block_a.x;
-    if (block_b.available)
-      bit_pos_b = 4*block_b.y + block_b.x;
+  if (enc_picture->chroma_format_idc!=YUV444 || IS_INDEPENDENT(params))
+  {
+    if (type!=LUMA_8x8)
+    {
+      if (block_b.available)
+      {
+        if(img->mb_data[block_b.mb_addr].mb_type==IPCM)
+          upper_bit=1;
+        else
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits[0],bit+bit_pos_b);
+      }
 
-    bit = 1; // 4x4: bit=1
+      if (block_a.available)
+      {
+        if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
+          left_bit=1;
+        else
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[0],bit+bit_pos_a);
+      }
 
+      ctx = 2*upper_bit+left_bit;
+      //===== encode symbol =====
+      estBits=estBitsCabac[type].blockCbpBits[ctx][0]-estBitsCabac[type].blockCbpBits[ctx][1];
+    }
+  }
+  else 
+  {
     if (block_b.available)
     {
-      if(img->mb_data[block_b.mb_addr].mb_type==IPCM)
+      if(img->mb_data[block_b.mb_addr].mb_type == IPCM)
         upper_bit=1;
       else
-        upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits[0],bit+bit_pos_b);
+      {
+        if(type==LUMA_8x8)
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits_8x8[0], bit + bit_pos_b);
+        else if (type==CB_8x8)
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits_8x8[1], bit + bit_pos_b);
+        else if (type==CR_8x8)
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits_8x8[2], bit + bit_pos_b);
+        else if ((type==CB_4x4)||(type==CB_4x8)||(type==CB_8x4)||(type==CB_16AC)||(type==CB_16DC))
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits[1], bit + bit_pos_b);
+        else if ((type==CR_4x4)||(type==CR_4x8)||(type==CR_8x4)||(type==CR_16AC)||(type==CR_16DC))
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits[2], bit + bit_pos_b);
+        else
+          upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].cbp_bits[0], bit + bit_pos_b);
+      }
     }
 
-
     if (block_a.available)
     {
       if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
-        left_bit=1;
+        left_bit = 1;
       else
-        left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[0],bit+bit_pos_a);
+      {
+        if(type==LUMA_8x8)
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[0],bit + bit_pos_a);
+        else if (type==CB_8x8)
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[1],bit + bit_pos_a);
+        else if (type==CR_8x8)
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits_8x8[2],bit + bit_pos_a);
+        else if ((type==CB_4x4)||(type==CB_4x8)||(type==CB_8x4)||(type==CB_16AC)||(type==CB_16DC))
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[1],bit + bit_pos_a);
+        else if ((type==CR_4x4)||(type==CR_4x8)||(type==CR_8x4)||(type==CR_16AC)||(type==CR_16DC))
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[2],bit + bit_pos_a);
+        else
+          left_bit = BIT_SET(img->mb_data[block_a.mb_addr].cbp_bits[0],bit + bit_pos_a);
+      }
     }
 
     ctx = 2*upper_bit+left_bit;
+
     //===== encode symbol =====
     estBits=estBitsCabac[type].blockCbpBits[ctx][0]-estBitsCabac[type].blockCbpBits[ctx][1];
   }
-  else
-  {
-    estBits=0;
-  }
+
   return(estBits);
 }
-
 /*!
 ****************************************************************************
 * \brief
@@ -361,7 +632,7 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
                              int noCoeff, int estCBP)
 {
   int   k, i;
-  int estBits;
+  int   estBits;
   double lagr, lagrMin=0, lagrTabMin, lagrTab;
   int   c1 = 1, c2 = 0, c1Tab[3], c2Tab[3];
   int   iBest, levelTab[64];
@@ -369,25 +640,24 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
   double   lagrAcc, lagrLastMin=0, lagrLast;
   int      kBest=0, kStart, first;
 
-  maxK=maxpos[type];
-  for (k=0; k<=maxK; k++)
+  maxK = maxpos[type];
+  for (k = 0; k <= maxK; k++)
   {
-    levelTabMin[k]=0;
+    levelTabMin[k] = 0;
   }
 
-  if (noCoeff>0)
+  if (noCoeff > 0)
   {
-    if (noCoeff>1)
+    if (noCoeff > 1)
     {
-      kStart=kInit; kBest=0; first=1; 
-
-      lagrAcc=0; 
-      for (k=kStart; k<=kStop; k++)
+      kStart = kInit; kBest = 0; first = 1; 
+      lagrAcc = 0; 
+      for (k = kStart; k <= kStop; k++)
       {
-        lagrAcc+=levelData[k].errLevel[0];
+        lagrAcc += levelData[k].errLevel[0];
       }
 
-      if (levelData[kStart].noLevels>2)
+      if (levelData[kStart].noLevels > 2)
       { 
         lagrAcc-=levelData[kStart].errLevel[0];
         lagrLastMin=lambda*(estBitsCabac[type].lastBits[pos2ctx_last[type][kStart]][1]-estBitsCabac[type].lastBits[pos2ctx_last[type][kStart]][0])+lagrAcc;
@@ -397,32 +667,30 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
         first=0;
       }
 
-      for (k=kStart; k<=kStop; k++)
+      for (k = kStart; k <= kStop; k++)
       {
         lagrMin=levelData[k].errLevel[0]+lambda*estBitsCabac[type].significantBits[pos2ctx_map[type][k]][0];
 
-        lagrAcc-=levelData[k].errLevel[0];
+        lagrAcc -= levelData[k].errLevel[0];
         if (levelData[k].noLevels>1)
         { 
-          estBits=SIGN_BITS+estBitsCabac[type].significantBits[pos2ctx_map[type][k]][1]+
+          estBits = SIGN_BITS+estBitsCabac[type].significantBits[pos2ctx_map[type][k]][1]+
             estBitsCabac[type].greaterOneBits[0][4][0];
 
-          lagrLast=levelData[k].errLevel[1]+lambda*(estBits+estBitsCabac[type].lastBits[pos2ctx_last[type][k]][1])+lagrAcc;
-          lagr=levelData[k].errLevel[1]+lambda*(estBits+estBitsCabac[type].lastBits[pos2ctx_last[type][k]][0]);
+          lagrLast = levelData[k].errLevel[1]+lambda*(estBits+estBitsCabac[type].lastBits[pos2ctx_last[type][k]][1])+lagrAcc;
+          lagr = levelData[k].errLevel[1]+lambda*(estBits+estBitsCabac[type].lastBits[pos2ctx_last[type][k]][0]);
 
           lagrMin=(lagr<lagrMin)?lagr:lagrMin;
 
-          if (lagrLast<lagrLastMin || first==1)
+          if (lagrLast < lagrLastMin || first==1)
           {
-            kBest=k;
-            first=0;
-            lagrLastMin=lagrLast;
+            kBest = k;
+            first = 0;
+            lagrLastMin = lagrLast;
           }
-
         }
         lagrAcc+=lagrMin;
       }
-
       kStart=kBest;
     }
     else
@@ -430,52 +698,52 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
       kStart=kStop;
     }
 
-    lagrTabMin=0;
-    for (k=0; k<=kStart; k++)
+    lagrTabMin = 0;
+    for (k = 0; k <= kStart; k++)
     {
-      lagrTabMin+=levelData[k].errLevel[0];
+      lagrTabMin += levelData[k].errLevel[0];
     }
     // Initial Lagrangian calculation
     lagrTab=0;
 
     //////////////////////////
 
-    lagrTabMin+=(lambda*estCBP);
-    iBest=0; first=1;
-    for (k=kStart; k>=0; k--)
+    lagrTabMin += (lambda*estCBP);
+    iBest = 0; first = 1;
+    for (k = kStart; k >= 0; k--)
     {
-      last=(k==kStart);
+      last = (k == kStart);
       if (!last)
       {
         lagrMin=levelData[k].errLevel[0]+lambda*estBitsCabac[type].significantBits[pos2ctx_map[type][k]][0];
-        iBest=0;
-        first=0;
+        iBest = 0;
+        first = 0;
       }
 
-      for (i=1; i < levelData[k].noLevels; i++)
+      for (i = 1; i < levelData[k].noLevels; i++)
       {
-        estBits=SIGN_BITS+estBitsCabac[type].significantBits[pos2ctx_map[type][k]][1];
-        estBits+=estBitsCabac[type].lastBits[pos2ctx_last[type][k]][last];
+        estBits = SIGN_BITS + estBitsCabac[type].significantBits[pos2ctx_map[type][k]][1];
+        estBits += estBitsCabac[type].lastBits[pos2ctx_last[type][k]][last];
 
         // greater than 1
-        greater_one = (levelData[k].level[i]>1);
+        greater_one = (levelData[k].level[i] > 1);
 
         c1Tab[i]=c1;   c2Tab[i]=c2;
 
-        ctx = imin(c1Tab[i],4);  
-        estBits+=estBitsCabac[type].greaterOneBits[0][ctx][greater_one];
+        ctx = imin(c1Tab[i], 4);  
+        estBits += estBitsCabac[type].greaterOneBits[0][ctx][greater_one];
 
         // magnitude if greater than 1
         if (greater_one)
         {
           ctx = imin(c2Tab[i], max_c2[type]);
-          if ((levelData[k].level[i]-2)<MAX_PREC_COEFF)
+          if ( (levelData[k].level[i] - 2) < MAX_PREC_COEFF)
           {
-            estBits+=precalcUnaryLevelTab[estBitsCabac[type].greaterOneState[ctx]][levelData[k].level[i]-2];
+            estBits += precalcUnaryLevelTab[estBitsCabac[type].greaterOneState[ctx]][levelData[k].level[i] - 2];
           }
           else
           {
-            estBits+=est_unary_exp_golomb_level_encode(levelData[k].level[i]-2, ctx, type);
+            estBits += est_unary_exp_golomb_level_encode(levelData[k].level[i] - 2, ctx, type);
           }
 
           c1Tab[i] = 0;
@@ -486,12 +754,12 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
           c1Tab[i]++;
         }
 
-        lagr=levelData[k].errLevel[i]+lambda*estBits;
+        lagr = levelData[k].errLevel[i] + lambda*estBits;
         if (lagr<lagrMin || first==1)
         {
-          iBest=i;
+          iBest = i;
           lagrMin=lagr;
-          first=0;
+          first = 0;
         }
       }
 
@@ -500,16 +768,16 @@ void est_writeRunLevel_CABAC(levelDataStruct levelData[], int levelTabMin[], int
         c1=c1Tab[iBest]; c2=c2Tab[iBest];
       }
 
-      levelTab[k]=levelData[k].level[iBest];
+      levelTab[k] = levelData[k].level[iBest];
       lagrTab+=lagrMin;
     }
     ///////////////////////////////////
 
-    if (lagrTab<lagrTabMin)
+    if (lagrTab < lagrTabMin)
     {
-      for (k=0; k<=kStart; k++)
+      for (k = 0; k <= kStart; k++)
       {
-        levelTabMin[k]=levelTab[k];
+        levelTabMin[k] = levelTab[k];
       }
     }
   }
@@ -575,6 +843,8 @@ void trellis_mp(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb)
   estRunLevel_CABAC(currMB, LUMA_16AC);
   if (params->Transform8x8Mode)
     estRunLevel_CABAC(currMB, LUMA_8x8);
+  if (params->yuv_format != YUV400)
+    estRunLevel_CABAC(currMB, CHROMA_AC);
 
   qp_left   = (currMB->mb_available_left) ? currMB->mb_available_left->qp : img->masterQP;
   qp_up     = (currMB->mb_available_up)   ? currMB->mb_available_up->qp   : img->masterQP;
@@ -611,20 +881,17 @@ void trellis_mp(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb)
 #endif
     if (img->current_mb_nr ==0 && deltaQP != 0)
       continue;
-    
+
     reset_macroblock(currMB, prev_mb);
     currMB->qp       = img->qp;
     currMB->delta_qp = currMB->qp - currMB->prev_qp;
-    update_qp (currMB);    
-    
-    delta_qp_mbaff[currMB->mb_field][img->bot_MB] = currMB->delta_qp;
-    qp_mbaff      [currMB->mb_field][img->bot_MB] = currMB->qp;
+    update_qp (img, currMB);    
 
     encode_one_macroblock (currMB);
 
     if ( rddata_trellis_curr.min_rdcost < rddata_trellis_best.min_rdcost)
       copy_rddata_trellis(&rddata_trellis_best,rdopt);
-    
+
     if (params->RDOQ_CP_MV)
       Motion_Selected = 1;
 
@@ -633,6 +900,8 @@ void trellis_mp(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb)
       break;
     if ((params->RDOQ_Fast) && (rddata_trellis_curr.cbp == 0) && (rddata_trellis_curr.mb_type != 0))
       break;
+    if ((params->RDOQ_Fast) && (rddata_trellis_best.mb_type == 0) && (rddata_trellis_best.cbp == 0))
+      break;
 #endif
   }
 
@@ -652,6 +921,8 @@ void trellis_sp(Macroblock *currMB, int CurrentMbAddr, Boolean prev_recode_mb)
   estRunLevel_CABAC(currMB, LUMA_16AC);
   if (params->Transform8x8Mode)
     estRunLevel_CABAC(currMB, LUMA_8x8);
+  if (params->yuv_format != YUV400)
+    estRunLevel_CABAC(currMB, CHROMA_AC);
 
   encode_one_macroblock (currMB);
   write_one_macroblock (currMB, 1, prev_recode_mb);    
@@ -721,7 +992,7 @@ void copy_rddata_trellis (RD_DATA *dest, RD_DATA *src)
   dest->delta_qp = src->delta_qp;
   dest->prev_cbp = src->prev_cbp;
   dest->cbp_blk = src->cbp_blk;
-  dest->bi_pred_me = src->bi_pred_me;
+ 
 
   if (img->type != I_SLICE)
   {
@@ -768,8 +1039,8 @@ void updateMV_mp(int *m_cost, short ref, int list, int h, int v, int blocktype,
       memcpy(img->all_mv[list][ref][blocktype][v+j][h+i], all_mv, 2 * sizeof(short));
   }
 
-  SetMotionVectorPredictor (currMB, pred_mv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, h<<2, v<<2, bsx, bsy);
-  
+  SetMotionVectorPredictor (currMB, pred_mv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, h<<2, v<<2, bsx, bsy);
+
   if ( (tmp_pred_mv[0] != pred_mv[0]) || (tmp_pred_mv[1] != pred_mv[1]) )
   {
     *m_cost -= MV_COST_SMP (lambda_factor[H_PEL], all_mv[0], all_mv[1], tmp_pred_mv[0], tmp_pred_mv[1]);
diff --git a/lencod/src/rdopt.c b/lencod/src/rdopt.c
index 3f61ca0..8ab8c05 100644
--- a/lencod/src/rdopt.c
+++ b/lencod/src/rdopt.c
@@ -22,6 +22,7 @@
 #include "global.h"
 
 #include "rdopt.h"
+#include "q_around.h"
 #include "rdopt_coding_state.h"
 #include "memalloc.h"
 #include "mb_access.h"
@@ -40,29 +41,13 @@
 #include "symbol.h"
 #include "q_offsets.h"
 #include "conformance.h"
+#include "errdo.h"
 
 imgpel pred[16][16];
 
 #define FASTMODE 1
 //#define RESET_STATE
 
-extern int   QP2QUANT[40];
-
-const int AdaptRndCrPos[2][5] =
-{
-  //  P,   B,   I,  SP,  SI
-  {   4,   7,   1,   4,   1}, // Intra MB
-  {  10,  13,  10,  10,  10}  // Inter MB
-};
-
-const int AdaptRndPos[4][5] =
-{
-  //  P,   B,   I,  SP,  SI
-  {   3,   6,   0,   3,   0}, // 4x4 Intra MB
-  {   1,   2,   0,   1,   2}, // 8x8 Intra MB
-  {   9,  12,   9,   9,   9}, // 4x4 Inter MB
-  {   3,   4,   3,   3,   3}, // 8x8 Inter MB
-};
 
 imgpel   rec_mbY[16][16], rec_mb_cr[2][16][16];    // reconstruction values
 
@@ -73,12 +58,6 @@ static int diff4x4[64];
 static int diff8x8[64];
 RD_8x8DATA tr4x4, tr8x8;
 
-int   **bestInterFAdjust4x4=NULL, **bestIntraFAdjust4x4=NULL;
-int   **bestInterFAdjust8x8=NULL, **bestIntraFAdjust8x8=NULL;
-int   ***bestInterFAdjust4x4Cr=NULL, ***bestIntraFAdjust4x4Cr=NULL;
-int   ***bestInterFAdjust8x8Cr=NULL, ***bestIntraFAdjust8x8Cr=NULL;
-int   **fadjust8x8=NULL, **fadjust4x4=NULL, ***fadjust4x4Cr=NULL, ***fadjust8x8Cr=NULL;
-
 
 int   ****cofAC=NULL, ****cofAC8x8=NULL;        // [8x8block][4x4block][level/run][scan_pos]
 int   ***cofDC=NULL;                       // [yuv][level/run][scan_pos]
@@ -86,18 +65,13 @@ int   **cofAC4x4=NULL, ****cofAC4x4intern=NULL; // [level/run][scan_pos]
 int   cbp, cbp8x8, cnt_nonz_8x8;
 int   cbp_blk8x8;
 char  l0_refframe[4][4], l1_refframe[4][4];
-short b8mode[4], b8pdir[4];
-short best8x8mode [4];                // [block]
-char  best8x8pdir  [MAXMODE][4];       // [mode][block]
-char  best8x8l0ref [MAXMODE][4];       // [mode][block]
-char  best8x8l1ref [MAXMODE][4];       // [mode][block]
-char  best8x8ref[2][MAXMODE][4];       // [mode][block]
+short b8mode[4], b8pdir[4], b8bipred_me[4];
 
 CSptr cs_mb=NULL, cs_b8=NULL, cs_cm=NULL, cs_ib8=NULL, cs_ib4=NULL;
 int   best_c_imode;
 int   best_i16offset;
 short best_mode;
-short  bi_pred_me;
+
 
 //mixed transform sizes definitions
 int   luma_transform_size_8x8_flag;
@@ -123,9 +97,6 @@ void StoreMV8x8(int dir);
 void RestoreMV8x8(int dir);
 // end of mixed transform sizes definitions
 
-//Adaptive Rounding update function
-void update_offset_params(Macroblock *currMB, int mode, int luma_transform_size_8x8_flag);
-
 char  b4_ipredmode[16], b4_intra_pred_modes[16];
 
 /*!
@@ -134,7 +105,7 @@ char  b4_ipredmode[16], b4_intra_pred_modes[16];
  *    delete structure for RD-optimized mode decision
  ************************************************************************
  */
-void clear_rdopt ()
+void clear_rdopt (InputParameters *params)
 {
   free_mem_DCcoeff (cofDC);
   free_mem_ACcoeff (cofAC);
@@ -160,24 +131,7 @@ void clear_rdopt ()
 
   if (params->AdaptiveRounding)
   {
-    free_mem2Dint(bestInterFAdjust4x4);
-    free_mem2Dint(bestIntraFAdjust4x4);
-    free_mem2Dint(bestInterFAdjust8x8);
-    free_mem2Dint(bestIntraFAdjust8x8);
-    free_mem2Dint(fadjust8x8);
-    free_mem2Dint(fadjust4x4);
-    if (params->yuv_format != 0)
-    {
-      if (params->yuv_format == YUV444)
-      {
-        free_mem3Dint(bestInterFAdjust8x8Cr);
-        free_mem3Dint(bestIntraFAdjust8x8Cr);
-      }
-      free_mem3Dint(bestInterFAdjust4x4Cr);
-      free_mem3Dint(bestIntraFAdjust4x4Cr);
-      free_mem3Dint(fadjust4x4Cr);
-      free_mem3Dint(fadjust8x8Cr);
-    }
+    clear_adaptive_rounding (params);
   }
 
   // structure for saving the coding state
@@ -195,7 +149,7 @@ void clear_rdopt ()
  *    create structure for RD-optimized mode decision
  ************************************************************************
  */
-void init_rdopt ()
+void init_rdopt (InputParameters *params)
 {
   rdopt = NULL;
 
@@ -226,6 +180,8 @@ void init_rdopt ()
     cofAC4x4CbCr[1] = cofAC4x4CbCrintern[1][0][0];    
   }
 
+  SetLagrangianMultipliers = params->rdopt == 0 ? SetLagrangianMultipliersOff : SetLagrangianMultipliersOn;
+
   switch (params->rdopt)
   {
   case 0:
@@ -244,24 +200,7 @@ void init_rdopt ()
   }
   if (params->AdaptiveRounding)
   {
-    get_mem2Dint(&bestInterFAdjust4x4, 16, 16);
-    get_mem2Dint(&bestIntraFAdjust4x4, 16, 16);
-    get_mem2Dint(&bestInterFAdjust8x8, 16, 16);
-    get_mem2Dint(&bestIntraFAdjust8x8, 16, 16);
-    get_mem2Dint(&fadjust8x8, 16, 16);
-    get_mem2Dint(&fadjust4x4, 16, 16);
-    if (params->yuv_format != 0 )
-    {
-      if  (params->yuv_format == YUV444)
-      {
-        get_mem3Dint(&bestInterFAdjust8x8Cr, 2, 16, 16);
-        get_mem3Dint(&bestIntraFAdjust8x8Cr, 2, 16, 16);
-      }
-      get_mem3Dint(&bestInterFAdjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
-      get_mem3Dint(&bestIntraFAdjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
-      get_mem3Dint(&fadjust4x4Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
-      get_mem3Dint(&fadjust8x8Cr, 2, img->mb_cr_size_y, img->mb_cr_size_x);
-    }
+    setup_adaptive_rounding (params);
   }
 
   // structure for saving the coding state
@@ -512,13 +451,12 @@ double RDCost_for_4x4IntraBlocks (Macroblock    *currMB,
   DataPartition  *dataPart;
 
   //===== perform DCT, Q, IQ, IDCT, Reconstruction =====
-  select_dct(currMB);
+  //select_dct(img, currMB);
   *nonzero = pDCT_4x4 (currMB, PLANE_Y, block_x, block_y, &dummy, 1);
 
   //===== get distortion (SSD) of 4x4 block =====
   distortion += compute_SSE(&pCurImg[pic_opix_y], &enc_picture->imgY[pic_pix_y], pic_pix_x, pic_pix_x, 4, 4);
 
-  ipmode_DPCM=NO_INTRA_PMODE;  //For residual DPCM
   if(img->P444_joined)
   {
     ColorPlane k;
@@ -530,6 +468,7 @@ double RDCost_for_4x4IntraBlocks (Macroblock    *currMB,
     }
     select_plane(PLANE_Y);
   }
+  ipmode_DPCM=NO_INTRA_PMODE;
 
   //===== RATE for INTRA PREDICTION MODE  (SYMBOL MODE MUST BE SET TO CAVLC) =====
   se.value1 = (mostProbableMode == ipmode) ? -1 : ipmode < mostProbableMode ? ipmode : ipmode - 1;
@@ -583,7 +522,9 @@ double RDCost_for_8x8blocks (Macroblock *currMB, // --> Current macroblock to co
                              int     mode,       // <-- partitioning mode
                              short   pdir,       // <-- prediction direction
                              short   l0_ref,     // <-- L0 reference picture
-                             short   l1_ref)     // <-- L1 reference picture
+                             short   l1_ref,     // <-- L1 reference picture
+                             short   bipred_me   // <-- bi prediction mode
+                             )     
 {
   int  k;
   int  rate=0;
@@ -609,8 +550,8 @@ double RDCost_for_8x8blocks (Macroblock *currMB, // --> Current macroblock to co
   //=====
   //=====  GET COEFFICIENTS, RECONSTRUCTIONS, CBP
   //=====
-  currMB->bi_pred_me=0;
-
+  currMB->bipred_me[block] = bipred_me;
+  
   if (direct)
   {
     if (direct_pdir[img->block_y+j0][img->block_x+i0]<0) // mode not allowed
@@ -646,15 +587,16 @@ double RDCost_for_8x8blocks (Macroblock *currMB, // --> Current macroblock to co
   {
     //===== get residue =====
     // We need the reconstructed prediction residue for the simulated decoders.
-    compute_residue_b8block (block, -1);
+    //compute_residue_b8block (img, &enc_picture->p_img[0][img->pix_y], decs->res_img[0], block, -1);
+    compute_residue_block (img, &enc_picture->p_img[0][img->pix_y], decs->res_img[0], img->mb_pred[0], block, 8);
 
     //=====
     //=====   GET DISTORTION
     //=====
     for (k=0; k<params->NoOfDecoders ;k++)
     {
-      decode_one_b8block (k, P8x8, block, mode, l0_ref);
-      distortion += compute_SSE(&pCurImg[img->opix_y+pay], &decs->decY[k][img->opix_y+pay], img->opix_x+pax, img->opix_x+pax, 8, 8);
+      decode_one_b8block (img, enc_picture, k, P8x8, block, mode, l0_ref);
+      distortion += compute_SSE(&pCurImg[img->opix_y+pay], &enc_picture->p_dec_img[0][k][img->opix_y+pay], img->opix_x+pax, img->opix_x+pax, 8, 8);
     }
     distortion /= params->NoOfDecoders;
   }
@@ -664,8 +606,8 @@ double RDCost_for_8x8blocks (Macroblock *currMB, // --> Current macroblock to co
 
     if (img->P444_joined)
     {
-      distortion += compute_SSE(&imgUV_org[0][img->opix_y + pay], &enc_picture->imgUV[0][img->pix_y + pay], img->opix_x + pax, img->pix_x + pax, 8, 8);
-      distortion += compute_SSE(&imgUV_org[1][img->opix_y + pay], &enc_picture->imgUV[1][img->pix_y + pay], img->opix_x + pax, img->pix_x + pax, 8, 8);
+      distortion += compute_SSE(&pImgOrg[1][img->opix_y + pay], &enc_picture->imgUV[0][img->pix_y + pay], img->opix_x + pax, img->pix_x + pax, 8, 8);
+      distortion += compute_SSE(&pImgOrg[2][img->opix_y + pay], &enc_picture->imgUV[1][img->pix_y + pay], img->opix_x + pax, img->pix_x + pax, 8, 8);
     }    
   }
 
@@ -709,11 +651,11 @@ double RDCost_for_8x8blocks (Macroblock *currMB, // --> Current macroblock to co
 
     if (pdir==0 || pdir==2)
     {
-      rate  += writeMotionVector8x8 (currMB, i0, j0, i0 + 2, j0 + 2, l0_ref, LIST_0, mode);
+      rate  += writeMotionVector8x8 (currMB, i0, j0, i0 + 2, j0 + 2, l0_ref, LIST_0, mode, currMB->bipred_me[block]);
     }
     if (pdir==1 || pdir==2)
     {
-      rate  += writeMotionVector8x8 (currMB, i0, j0, i0 + 2, j0 + 2, l1_ref, LIST_1, mode);
+      rate  += writeMotionVector8x8 (currMB, i0, j0, i0 + 2, j0 + 2, l1_ref, LIST_1, mode, currMB->bipred_me[block]);
     }
   }
 
@@ -764,16 +706,21 @@ int I16Offset (int cbp, int i16mode)
  */
 void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
 {
-  int i,j,k,l;
+  int i,j,k,l; 
   int  bframe  = (img->type==B_SLICE);
-  int  block_x, block_y;
+  int  block_x, block_y, block8x8, block4x4;
   int  cur_ref;
   int  clist;
-  char cref[2];
+  char cref[2], curref, bestref;
+  Block8x8Info *b8x8info = img->b8x8info;
 
   //--- macroblock type ---
   currMB->mb_type = mode;
-  currMB->bi_pred_me= (mode == 1 ? img->bi_pred_me[mode] : 0);
+  
+   for( i = 0; i < 4; i++) 
+   {
+     currMB->bipred_me[i] = b8x8info->bipred8x8me[mode][i];
+   }
 
   //--- block 8x8 mode and prediction direction ---
   switch (mode)
@@ -798,14 +745,14 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
     for(i=0;i<4;i++)
     {
       currMB->b8mode[i] = mode;
-      currMB->b8pdir[i] = best8x8pdir[mode][i];
+      currMB->b8pdir[i] = b8x8info->best8x8pdir[mode][i];
     }
     break;
   case P8x8:
-    memcpy(currMB->b8mode, best8x8mode, 4 * sizeof(short));
+    memcpy(currMB->b8mode, b8x8info->best8x8mode, 4 * sizeof(short));
     for(i=0;i<4;i++)
     {
-      currMB->b8pdir[i]   = best8x8pdir[mode][i];
+      currMB->b8pdir[i]   = b8x8info->best8x8pdir[mode][i];
     }
     break;
   case I4MB:
@@ -844,8 +791,9 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
     exit (1);
   }
 
-#define IS_FW ((best8x8pdir[mode][k]==0 || best8x8pdir[mode][k]==2) && (mode!=P8x8 || best8x8mode[k]!=0 || !bframe))
-#define IS_BW ((best8x8pdir[mode][k]==1 || best8x8pdir[mode][k]==2) && (mode!=P8x8 || best8x8mode[k]!=0))
+#define IS_FW ((b8x8info->best8x8pdir[mode][k]==0 || b8x8info->best8x8pdir[mode][k]==2) && (mode!=P8x8 || b8x8info->best8x8mode[k]!=0 || !bframe))
+#define IS_BW ((b8x8info->best8x8pdir[mode][k]==1 || b8x8info->best8x8pdir[mode][k]==2) && (mode!=P8x8 || b8x8info->best8x8mode[k]!=0))
+  
   //--- reference frame arrays ---
   if (mode==0 || mode==I4MB || mode==I16MB || mode==I8MB)
   {
@@ -857,7 +805,7 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
         {
           for (j = img->block_y; j < img->block_y + 4; j++)
           {
-            memcpy(&enc_picture->ref_idx[clist][j][img->block_x], &direct_ref_idx[clist][j][img->block_x], 4 * sizeof(char));
+            memcpy(&enc_picture->motion.ref_idx[clist][j][img->block_x], &direct_ref_idx[clist][j][img->block_x], 4 * sizeof(char));
           }
         }
       }
@@ -867,7 +815,7 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
         {
           for (j = img->block_y; j < img->block_y + 4; j++)
           {
-            memset(&enc_picture->ref_idx[clist][j][img->block_x],-1, 4 * sizeof(char));
+            memset(&enc_picture->motion.ref_idx[clist][j][img->block_x],-1, 4 * sizeof(char));
           }
         }
       }
@@ -877,12 +825,12 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
       if (!mode) // Skip
       {
         for (j = img->block_y; j < img->block_y + 4; j++)
-          memset(&enc_picture->ref_idx[LIST_0][j][img->block_x],0, 4 * sizeof(char));
+          memset(&enc_picture->motion.ref_idx[LIST_0][j][img->block_x],0, 4 * sizeof(char));
       }
       else // Intra
       {
         for (j = img->block_y; j < img->block_y + 4; j++)
-          memset(&enc_picture->ref_idx[LIST_0][j][img->block_x],-1, 4 * sizeof(char));
+          memset(&enc_picture->motion.ref_idx[LIST_0][j][img->block_x],-1, 4 * sizeof(char));
       }
     }
   }
@@ -890,73 +838,33 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
   {
     if (bframe)
     {
-      if (mode == 1)
+      if (mode == 1 || mode == 2 || mode == 3) 
       {
-        if (currMB->bi_pred_me && best8x8pdir[mode][0] == 2)
+        for (block8x8 = 0; block8x8 < 4; block8x8++)
         {
           for (clist = LIST_0; clist <= LIST_1; clist++)
           {
-            for (j = img->block_y; j < img->block_y + 4;j++)
-            {          
-              memset(&enc_picture->ref_idx[clist][j][img->block_x], 0, 4 * sizeof(char));
+            bestref = (clist == LIST_0) ? b8x8info->best8x8l0ref[mode][block8x8] :  b8x8info->best8x8l1ref[mode][block8x8];
+            if ( b8x8info->best8x8pdir[mode][block8x8] == 2)
+            {
+              if (b8x8info->bipred8x8me[mode][block8x8])
+                curref = 0;
+              else  
+                curref = bestref;
             }
-          }
-        }
-        else
-        {
-          cref[0] = (best8x8pdir[mode][0] == 0 || best8x8pdir[mode][0] == 2) ? best8x8l0ref[mode][0] : -1;
-          cref[1] = (best8x8pdir[mode][0] == 1 || best8x8pdir[mode][0] == 2) ? best8x8l1ref[mode][0] : -1;
-          for (clist = LIST_0; clist <= LIST_1; clist++)
-          {
-            for (j = img->block_y; j < img->block_y + 4;j++)
-            {          
-              memset(&enc_picture->ref_idx[clist][j][img->block_x], cref[clist], 4 * sizeof(char));
+            else
+            {
+              curref = (clist == b8x8info->best8x8pdir[mode][block8x8]) ? bestref : -1;
+            }
+            for (block4x4 = 0; block4x4 < 4; block4x4++)
+            {
+              block_x = img->block_x + 2 * (block8x8 & 0x01) + (block4x4 & 0x01);
+              block_y = img->block_y + 2 * (block8x8 >> 1) + (block4x4 >> 1);
+              enc_picture->motion.ref_idx[clist][block_y][block_x] = curref;
             }
           }
         }
       }
-      else if (mode == 2)
-      {
-        j = img->block_y;
-        cref[0] = (best8x8pdir[mode][0] == 0 || best8x8pdir[mode][0] == 2) ? best8x8l0ref[mode][0] : -1;
-        cref[1] = (best8x8pdir[mode][0] == 1 || best8x8pdir[mode][0] == 2) ? best8x8l1ref[mode][0] : -1;        
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_1][j++][img->block_x], cref[1], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_1][j++][img->block_x], cref[1], 4 * sizeof(char));
-
-        cref[0] = (best8x8pdir[mode][2] == 0 || best8x8pdir[mode][2] == 2) ? best8x8l0ref[mode][2] : -1;
-        cref[1] = (best8x8pdir[mode][2] == 1 || best8x8pdir[mode][2] == 2) ? best8x8l1ref[mode][2] : -1;
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_1][j++][img->block_x], cref[1], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_1][j++][img->block_x], cref[1], 4 * sizeof(char));
-      }
-      else if (mode == 3)
-      {
-        j = img->block_y;
-        i = img->block_x;
-        cref[0] = (best8x8pdir[mode][0] == 0 || best8x8pdir[mode][0] == 2) ? best8x8l0ref[mode][0] : -1;
-        cref[1] = (best8x8pdir[mode][0] == 1 || best8x8pdir[mode][0] == 2) ? best8x8l1ref[mode][0] : -1;
-        enc_picture->ref_idx[LIST_0][j  ][i  ] = cref[0];
-        enc_picture->ref_idx[LIST_1][j  ][i++] = cref[1];
-        enc_picture->ref_idx[LIST_0][j  ][i  ] = cref[0];
-        enc_picture->ref_idx[LIST_1][j  ][i++] = cref[1];
-
-        cref[0] = (best8x8pdir[mode][1] == 0 || best8x8pdir[mode][1] == 2) ? best8x8l0ref[mode][1] : -1;
-        cref[1] = (best8x8pdir[mode][1] == 1 || best8x8pdir[mode][1] == 2) ? best8x8l1ref[mode][1] : -1;
-        enc_picture->ref_idx[LIST_0][j  ][i  ] = cref[0];
-        enc_picture->ref_idx[LIST_1][j  ][i++] = cref[1];
-        enc_picture->ref_idx[LIST_0][j  ][i  ] = cref[0];
-        enc_picture->ref_idx[LIST_1][j++][i  ] = cref[1];
-
-        memcpy(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_1][j++][img->block_x], &enc_picture->ref_idx[LIST_1][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_1][j++][img->block_x], &enc_picture->ref_idx[LIST_1][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_1][j++][img->block_x], &enc_picture->ref_idx[LIST_1][img->block_y][img->block_x], 4 * sizeof(char));
-      }      
       else
       {
         for (j=0;j<4;j++)
@@ -968,15 +876,15 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
             k = 2*(j >> 1) + (i >> 1);
             l = 2*(j & 0x01) + (i & 0x01);
 
-            if(mode == P8x8 && best8x8mode[k]==0)
+            if(mode == P8x8 && b8x8info->best8x8mode[k]==0)
             {
-              enc_picture->ref_idx[LIST_0][block_y][block_x] = direct_ref_idx[LIST_0][block_y][block_x];
-              enc_picture->ref_idx[LIST_1][block_y][block_x] = direct_ref_idx[LIST_1][block_y][block_x];
+              enc_picture->motion.ref_idx[LIST_0][block_y][block_x] = direct_ref_idx[LIST_0][block_y][block_x];
+              enc_picture->motion.ref_idx[LIST_1][block_y][block_x] = direct_ref_idx[LIST_1][block_y][block_x];
             }
             else
             {
-              enc_picture->ref_idx[LIST_0][block_y][block_x] = (IS_FW ? best8x8l0ref[mode][k] : -1);
-              enc_picture->ref_idx[LIST_1][block_y][block_x] = (IS_BW ? best8x8l1ref[mode][k] : -1);
+              enc_picture->motion.ref_idx[LIST_0][block_y][block_x] = (IS_FW ? b8x8info->best8x8l0ref[mode][k] : -1);
+              enc_picture->motion.ref_idx[LIST_1][block_y][block_x] = (IS_BW ? b8x8info->best8x8l1ref[mode][k] : -1);
             }
           }        
         }
@@ -986,36 +894,36 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
     {
       if (mode == 1)
       {
-        cref[0] = best8x8pdir[mode][0] == 0 ? best8x8l0ref[mode][0] : -1;
+        cref[0] = b8x8info->best8x8pdir[mode][0] == 0 ? b8x8info->best8x8l0ref[mode][0] : -1;
         j = img->block_y;
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
       }
       else if (mode == 2)
       {
-        cref[0] = best8x8pdir[mode][0] == 0 ? best8x8l0ref[mode][0] : -1;
+        cref[0] = b8x8info->best8x8pdir[mode][0] == 0 ? b8x8info->best8x8l0ref[mode][0] : -1;
         j = img->block_y;
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        cref[0] = best8x8pdir[mode][2] == 0 ? best8x8l0ref[mode][2] : -1;
-        memset(&enc_picture->ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
-        memset(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        cref[0] = b8x8info->best8x8pdir[mode][2] == 0 ? b8x8info->best8x8l0ref[mode][2] : -1;
+        memset(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], cref[0], 4 * sizeof(char));
+        memset(&enc_picture->motion.ref_idx[LIST_0][j  ][img->block_x], cref[0], 4 * sizeof(char));
       }      
       else if (mode == 3)
       {
         j = img->block_y;
         i = img->block_x;
-        cref[0] = (best8x8pdir[mode][0] == 0) ? best8x8l0ref[mode][0] : -1;
-        enc_picture->ref_idx[LIST_0][j  ][i++] = cref[0];
-        enc_picture->ref_idx[LIST_0][j  ][i++] = cref[0];
-        cref[0] = (best8x8pdir[mode][1] == 0) ? best8x8l0ref[mode][1] : -1;
-        enc_picture->ref_idx[LIST_0][j  ][i++] = cref[0];
-        enc_picture->ref_idx[LIST_0][j++][i  ] = cref[0];
-        memcpy(&enc_picture->ref_idx[LIST_0][j++][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_0][j++][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
-        memcpy(&enc_picture->ref_idx[LIST_0][j  ][img->block_x], &enc_picture->ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
+        cref[0] = (b8x8info->best8x8pdir[mode][0] == 0) ? b8x8info->best8x8l0ref[mode][0] : -1;
+        enc_picture->motion.ref_idx[LIST_0][j  ][i++] = cref[0];
+        enc_picture->motion.ref_idx[LIST_0][j  ][i++] = cref[0];
+        cref[0] = (b8x8info->best8x8pdir[mode][1] == 0) ? b8x8info->best8x8l0ref[mode][1] : -1;
+        enc_picture->motion.ref_idx[LIST_0][j  ][i++] = cref[0];
+        enc_picture->motion.ref_idx[LIST_0][j++][i  ] = cref[0];
+        memcpy(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], &enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
+        memcpy(&enc_picture->motion.ref_idx[LIST_0][j++][img->block_x], &enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
+        memcpy(&enc_picture->motion.ref_idx[LIST_0][j  ][img->block_x], &enc_picture->motion.ref_idx[LIST_0][img->block_y][img->block_x], 4 * sizeof(char));
       }      
       else
       {
@@ -1027,7 +935,7 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
             block_x = img->block_x + i;
             k = 2*(j >> 1) + (i >> 1);
             l = 2*(j & 0x01) + (i & 0x01);
-            enc_picture->ref_idx[LIST_0][block_y][block_x] = (IS_FW ? best8x8l0ref[mode][k] : -1);
+            enc_picture->motion.ref_idx[LIST_0][block_y][block_x] = (IS_FW ? b8x8info->best8x8l0ref[mode][k] : -1);
           }
         }
       }
@@ -1041,8 +949,8 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
       for (j = img->block_y; j < img->block_y + 4; j++)
         for (i = img->block_x; i < img->block_x + 4;i++)
         {
-          cur_ref = (int) enc_picture->ref_idx[clist][j][i];
-          enc_picture->ref_pic_id [clist][j][i] = (cur_ref>=0
+          cur_ref = (int) enc_picture->motion.ref_idx[clist][j][i];
+          enc_picture->motion.ref_pic_id [clist][j][i] = (cur_ref>=0
             ? enc_picture->ref_pic_num[clist + currMB->list_offset][cur_ref]
             : -1);
         }
@@ -1053,8 +961,8 @@ void SetModesAndRefframeForBlocks (Macroblock *currMB, int mode)
     for (j = img->block_y; j < img->block_y + 4; j++)
       for (i = img->block_x; i < img->block_x + 4;i++)
       {
-        cur_ref = (int) enc_picture->ref_idx[LIST_0][j][i];
-        enc_picture->ref_pic_id [LIST_0][j][i] = (cur_ref>=0
+        cur_ref = (int) enc_picture->motion.ref_idx[LIST_0][j][i];
+        enc_picture->motion.ref_pic_id [LIST_0][j][i] = (cur_ref>=0
           ? enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][cur_ref]
           : -1);
       }
@@ -1100,8 +1008,8 @@ void SetCoeffAndReconstruction8x8 (Macroblock* currMB)
         {
           k = 2*(j >> 1)+(i >> 1);
           l = 2*(j & 0x01)+(i & 0x01);
-          enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x+i] = ((currMB->b8pdir[k] & 0x01) == 0) ? tr8x8.part8x8l0ref[k] : - 1;
-          enc_picture->ref_idx[LIST_1][img->block_y+j][img->block_x+i] =  (currMB->b8pdir[k] > 0)          ? tr8x8.part8x8l1ref[k] : - 1;
+          enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x+i] = ((currMB->b8pdir[k] & 0x01) == 0) ? tr8x8.part8x8l0ref[k] : - 1;
+          enc_picture->motion.ref_idx[LIST_1][img->block_y+j][img->block_x+i] =  (currMB->b8pdir[k] > 0)          ? tr8x8.part8x8l1ref[k] : - 1;
         }
     }
     else
@@ -1111,7 +1019,7 @@ void SetCoeffAndReconstruction8x8 (Macroblock* currMB)
         {
           k = 2*(j >> 1)+(i >> 1);
           l = 2*(j & 0x01)+(i & 0x01);
-          enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x+i] = tr8x8.part8x8l0ref[k];
+          enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x+i] = tr8x8.part8x8l0ref[k];
         }
     }
 
@@ -1120,9 +1028,9 @@ void SetCoeffAndReconstruction8x8 (Macroblock* currMB)
     {
       for (i = img->block_x;i<img->block_x + BLOCK_MULTIPLE;i++)
       {
-        cur_ref = (int) enc_picture->ref_idx[LIST_0][j][i];
+        cur_ref = (int) enc_picture->motion.ref_idx[LIST_0][j][i];
 
-        enc_picture->ref_pic_id [LIST_0][j][i] =(cur_ref>=0
+        enc_picture->motion.ref_pic_id [LIST_0][j][i] =(cur_ref>=0
           ? enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][cur_ref]
           : -1);
       }
@@ -1134,9 +1042,9 @@ void SetCoeffAndReconstruction8x8 (Macroblock* currMB)
       {
         for (i = img->block_x;i<img->block_x + BLOCK_MULTIPLE;i++)
         {
-          cur_ref = (int) enc_picture->ref_idx[LIST_1][j][i];
+          cur_ref = (int) enc_picture->motion.ref_idx[LIST_1][j][i];
 
-          enc_picture->ref_pic_id [LIST_1][j][i] = (cur_ref>=0
+          enc_picture->motion.ref_pic_id [LIST_1][j][i] = (cur_ref>=0
             ? enc_picture->ref_pic_num[LIST_1 + currMB->list_offset][cur_ref]
             : -1);
         }
@@ -1291,6 +1199,12 @@ void SetCoeffAndReconstruction8x8 (Macroblock* currMB)
       {
         memcpy (&enc_picture->imgY[img->pix_y+j][img->pix_x],tr4x4.rec_mbY8x8[j], MB_BLOCK_SIZE * sizeof(imgpel));
       }
+
+      if (params->rdopt == 3)
+      {
+        errdo_get_best_block(img, enc_picture->p_dec_img[0], decs->dec_mbY8x8, 0, MB_BLOCK_SIZE);
+      }
+
       if(img->type==SP_SLICE &&(!si_frame_indicator && !sp2_frame_indicator))
       {
         for (j = 0; j < MB_BLOCK_SIZE; j++)
@@ -1323,6 +1237,7 @@ void SetMotionVectorsMB (Macroblock* currMB, int bframe)
   int i, j, k, l, mode8, pdir8, ref, by, bx;
   short ******all_mv  = img->all_mv;
   short ******pred_mv = img->pred_mv;
+  short bipred_me8;
   int  l1_ref;
   int jdiv, jmod;
 
@@ -1341,17 +1256,17 @@ void SetMotionVectorsMB (Macroblock* currMB, int bframe)
         bx   = img->block_x+i;
 
         pdir8 = currMB->b8pdir[k];
-        ref    = enc_picture->ref_idx[LIST_0][by][bx];
+        ref    = enc_picture->motion.ref_idx[LIST_0][by][bx];
 
         if (pdir8>=0)
         {
-          enc_picture->mv[LIST_0][by][bx][0] = all_mv [LIST_0][ ref][mode8][j][i][0];
-          enc_picture->mv[LIST_0][by][bx][1] = all_mv [LIST_0][ ref][mode8][j][i][1];
+          enc_picture->motion.mv[LIST_0][by][bx][0] = all_mv [LIST_0][ ref][mode8][j][i][0];
+          enc_picture->motion.mv[LIST_0][by][bx][1] = all_mv [LIST_0][ ref][mode8][j][i][1];
         }
         else
         {
-          enc_picture->mv[LIST_0][by][bx][0] = 0;
-          enc_picture->mv[LIST_0][by][bx][1] = 0;
+          enc_picture->motion.mv[LIST_0][by][bx][0] = 0;
+          enc_picture->motion.mv[LIST_0][by][bx][1] = 0;
         }
       }
     }
@@ -1366,50 +1281,55 @@ void SetMotionVectorsMB (Macroblock* currMB, int bframe)
       for (i = 0; i<4; i++)
       {
         mode8 = currMB->b8mode[k=2*jdiv+(i>>1)];
+        bipred_me8  = currMB->bipred_me[k]; 
         l     = 2*jmod + (i & 0x01);
 
         bx    = img->block_x+i;
 
         pdir8 = currMB->b8pdir[k];
-        ref    = enc_picture->ref_idx[LIST_0][by][bx];
-        l1_ref = enc_picture->ref_idx[LIST_1][by][bx];
+        ref    = enc_picture->motion.ref_idx[LIST_0][by][bx];
+        l1_ref = enc_picture->motion.ref_idx[LIST_1][by][bx];
 
-        if (currMB->bi_pred_me && (pdir8 == 2) && currMB->mb_type==1)
+        if ( bipred_me8 && (pdir8 == 2) && is_bipred_enabled(currMB->mb_type))
         {
-          all_mv  = currMB->bi_pred_me == 1 ? img->bipred_mv1 : img->bipred_mv2;
+          all_mv  = img->bipred_mv[bipred_me8 - 1]; 
           ref = 0;
           l1_ref = 0;
         }
+        else
+        {
+          all_mv  = img->all_mv;
+        }
 
         if (pdir8==-1) // intra
         {
-          enc_picture->mv[LIST_0][by][bx][0] = 0;
-          enc_picture->mv[LIST_0][by][bx][1] = 0;
-          enc_picture->mv[LIST_1][by][bx][0] = 0;
-          enc_picture->mv[LIST_1][by][bx][1] = 0;
+          enc_picture->motion.mv[LIST_0][by][bx][0] = 0;
+          enc_picture->motion.mv[LIST_0][by][bx][1] = 0;
+          enc_picture->motion.mv[LIST_1][by][bx][0] = 0;
+          enc_picture->motion.mv[LIST_1][by][bx][1] = 0;
         }
         else if (pdir8==0) // list 0
         {
-          enc_picture->mv[LIST_0][by][bx][0] = all_mv [LIST_0][ ref][mode8][j][i][0];
-          enc_picture->mv[LIST_0][by][bx][1] = all_mv [LIST_0][ ref][mode8][j][i][1];
-          enc_picture->mv[LIST_1][by][bx][0] = 0;
-          enc_picture->mv[LIST_1][by][bx][1] = 0;
-          enc_picture->ref_idx[LIST_1][by][bx] = -1;
+          enc_picture->motion.mv[LIST_0][by][bx][0]   = all_mv [LIST_0][ ref][mode8][j][i][0];
+          enc_picture->motion.mv[LIST_0][by][bx][1]   = all_mv [LIST_0][ ref][mode8][j][i][1];
+          enc_picture->motion.mv[LIST_1][by][bx][0]   = 0;
+          enc_picture->motion.mv[LIST_1][by][bx][1]   = 0;
+          enc_picture->motion.ref_idx[LIST_1][by][bx] = -1;
         }
         else if (pdir8==1) // list 1
         {
-          enc_picture->mv[LIST_0][by][bx][0] = 0;
-          enc_picture->mv[LIST_0][by][bx][1] = 0;
-          enc_picture->ref_idx[LIST_0][by][bx] = -1;
-          enc_picture->mv[LIST_1][by][bx][0] = all_mv [LIST_1][l1_ref][mode8][j][i][0];
-          enc_picture->mv[LIST_1][by][bx][1] = all_mv [LIST_1][l1_ref][mode8][j][i][1];
+          enc_picture->motion.mv[LIST_0][by][bx][0]   = 0;
+          enc_picture->motion.mv[LIST_0][by][bx][1]   = 0;
+          enc_picture->motion.ref_idx[LIST_0][by][bx] = -1;
+          enc_picture->motion.mv[LIST_1][by][bx][0]   = all_mv [LIST_1][l1_ref][mode8][j][i][0];
+          enc_picture->motion.mv[LIST_1][by][bx][1]   = all_mv [LIST_1][l1_ref][mode8][j][i][1];
         }
         else if (pdir8==2) // bipredictive
         {
-          enc_picture->mv[LIST_0][by][bx][0] = all_mv [LIST_0][ ref][mode8][j][i][0];
-          enc_picture->mv[LIST_0][by][bx][1] = all_mv [LIST_0][ ref][mode8][j][i][1];
-          enc_picture->mv[LIST_1][by][bx][0] = all_mv [LIST_1][l1_ref][mode8][j][i][0];
-          enc_picture->mv[LIST_1][by][bx][1] = all_mv [LIST_1][l1_ref][mode8][j][i][1];
+          enc_picture->motion.mv[LIST_0][by][bx][0] = all_mv [LIST_0][   ref][mode8][j][i][0];
+          enc_picture->motion.mv[LIST_0][by][bx][1] = all_mv [LIST_0][   ref][mode8][j][i][1];
+          enc_picture->motion.mv[LIST_1][by][bx][0] = all_mv [LIST_1][l1_ref][mode8][j][i][0];
+          enc_picture->motion.mv[LIST_1][by][bx][1] = all_mv [LIST_1][l1_ref][mode8][j][i][1];
         }
         else
         {
@@ -1457,7 +1377,7 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
   int         use_of_cc =  (img->type!=I_SLICE &&  params->symbol_mode!=CABAC);
   int         cc_rate, dummy;
   double      dummy_d;
-  imgpel     (*curr_mpr)[16] = img->mpr[0];
+  imgpel     (*mb_pred)[16] = img->mb_pred[0];
   imgpel     (*curr_mpr_16x16)[16][16] = img->mpr_16x16[0];
 
   //=====
@@ -1545,8 +1465,8 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
       {
         j1 = j + img->opix_c_y;
         j2 = j + img->pix_c_y;
-        memcpy(&enc_picture->imgUV[0][j2][img->opix_c_x], &imgUV_org[0][j1][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
-        memcpy(&enc_picture->imgUV[1][j2][img->opix_c_x], &imgUV_org[1][j1][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
+        memcpy(&enc_picture->imgUV[0][j2][img->opix_c_x], &pImgOrg[1][j1][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
+        memcpy(&enc_picture->imgUV[1][j2][img->opix_c_x], &pImgOrg[2][j1][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
       }
     }
     for (j=0;j<4;j++)
@@ -1558,7 +1478,9 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
   if (params->rdopt==3 && img->type!=B_SLICE)
   {
     // We need the reconstructed prediction residue for the simulated decoders.
-    compute_residue_mb (mode == I16MB ? i16mode : -1);
+    // Should we be handing imgY here or p_curr_img instead of p_img[0]? This could make it more generic
+    ////compute_residue_mb (img, &enc_picture->p_img[0][img->pix_y], decs->res_img[0], mode == I16MB ? i16mode : -1);
+    compute_residue_block (img, &enc_picture->p_curr_img[img->pix_y], decs->res_img[0], mode == I16MB ? img->mpr_16x16[0][i16mode] : img->mb_pred[0], 0, 16);
   }
 
   //Rate control
@@ -1567,7 +1489,7 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
     if (mode == I16MB)
       memcpy(pred, curr_mpr_16x16[i16mode], MB_PIXELS * sizeof(imgpel));
     else
-      memcpy(pred, curr_mpr, MB_PIXELS * sizeof(imgpel));
+      memcpy(pred, mb_pred, MB_PIXELS * sizeof(imgpel));
   }
 
   img->i16offset = 0;
@@ -1583,20 +1505,30 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
   //=====   GET DISTORTION
   //=====
   // LUMA
-  if (params->rdopt==3 && img->type!=B_SLICE)
+  if (params->rdopt == 3 && img->type!=B_SLICE)
   {
-    for (k = 0; k<params->NoOfDecoders ;k++)
+    if (mode != P8x8)
+    {
+      for (k = 0; k<params->NoOfDecoders ;k++)
+      {
+        decode_one_mb (img, enc_picture, k, currMB);
+        distortion += compute_SSE(&pCurImg[img->opix_y], &enc_picture->p_dec_img[0][k][img->opix_y], img->opix_x, img->opix_x, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
+      }
+    }
+    else
     {
-      decode_one_mb (k, currMB);
-      distortion += compute_SSE(&pCurImg[img->opix_y], &decs->decY[k][img->opix_y], img->opix_x, img->opix_x, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
+      for (k = 0; k<params->NoOfDecoders ;k++)
+      {
+        distortion += compute_SSE(&pCurImg[img->opix_y], &enc_picture->p_dec_img[0][k][img->opix_y], img->opix_x, img->opix_x, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
+      }
     }
     distortion /= params->NoOfDecoders;
 
     if ((img->yuv_format != YUV400) && (active_sps->chroma_format_idc != YUV444))
     {
       // CHROMA
-      distortion += compute_SSE(&imgUV_org[0][img->opix_c_y], &enc_picture->imgUV[0][img->pix_c_y], img->opix_c_x, img->pix_c_x, img->mb_cr_size_y, img->mb_cr_size_x);
-      distortion += compute_SSE(&imgUV_org[1][img->opix_c_y], &enc_picture->imgUV[1][img->pix_c_y], img->opix_c_x, img->pix_c_x, img->mb_cr_size_y, img->mb_cr_size_x);
+      distortion += compute_SSE(&pImgOrg[1][img->opix_c_y], &enc_picture->imgUV[0][img->pix_c_y], img->opix_c_x, img->pix_c_x, img->mb_cr_size_y, img->mb_cr_size_x);
+      distortion += compute_SSE(&pImgOrg[2][img->opix_c_y], &enc_picture->imgUV[1][img->pix_c_y], img->opix_c_x, img->pix_c_x, img->mb_cr_size_y, img->mb_cr_size_x);
     }
   }
   else
@@ -1644,7 +1576,7 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
 
   if (rdcost >= *min_rdcost ||
     ((currMB->qp_scaled[0]) == 0 && img->lossless_qpprime_flag == 1 && distortion != 0))
-  {    
+  {
 #if FASTMODE
     // Reordering RDCost comparison order of mode 0 and mode 1 in P_SLICE
     // if RDcost of mode 0 and mode 1 is same, we choose best_mode is 0
@@ -1681,111 +1613,6 @@ int RDCost_for_macroblocks (Macroblock  *currMB,   // <-- Current Macroblock to
   return 1;
 }
 
-/*!
- *************************************************************************************
- * \brief
- *    Store adaptive rounding parameters
- *************************************************************************************
- */
-void store_adaptive_rounding_parameters (Macroblock *currMB, int mode)
-{
-  int j;
-  int is_inter = (mode != I4MB)&&(mode != I16MB)&&(mode != I8MB);
-
-  if (currMB->luma_transform_size_8x8_flag)
-  {
-    if ((mode == P8x8))
-      memcpy(&(bestInterFAdjust8x8[0][0]),&(img->fadjust8x8[2][0][0]), MB_PIXELS * sizeof(int));
-    else if (is_inter)
-      memcpy(&(bestInterFAdjust8x8[0][0]),&(img->fadjust8x8[0][0][0]), MB_PIXELS * sizeof(int));
-    else
-      memcpy(&(bestIntraFAdjust8x8[0][0]),&(img->fadjust8x8[1][0][0]), MB_PIXELS * sizeof(int));
-  }
-  else
-  {
-    if ((mode == P8x8))
-      memcpy(&(bestInterFAdjust4x4[0][0]),&(img->fadjust4x4[3][0][0]),MB_PIXELS * sizeof(int));
-    else if (is_inter)
-      memcpy(&(bestInterFAdjust4x4[0][0]),&(img->fadjust4x4[0][0][0]),MB_PIXELS * sizeof(int));
-    else
-      memcpy(&(bestIntraFAdjust4x4[0][0]),&(img->fadjust4x4[1 + mode == I16MB][0][0]),MB_PIXELS * sizeof(int));
-  }
-
-  if (img->P444_joined)
-  {
-    if (currMB->luma_transform_size_8x8_flag)
-    {
-      if ((mode == P8x8))
-      {
-        memcpy(&(bestInterFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][2][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestInterFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][2][0][0]),MB_PIXELS * sizeof(int));
-      }
-      else if (is_inter)
-      {
-        memcpy(&(bestInterFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][0][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestInterFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][0][0][0]),MB_PIXELS * sizeof(int));
-      }
-      else
-      {
-        memcpy(&(bestIntraFAdjust8x8Cr[0][0][0]),&(img->fadjust8x8Cr[0][1][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestIntraFAdjust8x8Cr[1][0][0]),&(img->fadjust8x8Cr[1][1][0][0]),MB_PIXELS * sizeof(int));
-      }
-    }
-    else
-    {
-      if ((mode == P8x8))
-      {
-        memcpy(&(bestInterFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][3][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestInterFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][3][0][0]),MB_PIXELS * sizeof(int));
-      }
-      else if (is_inter)
-      {
-        memcpy(&(bestInterFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][0][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestInterFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][0][0][0]),MB_PIXELS * sizeof(int));
-      }
-      else
-      {
-        memcpy(&(bestIntraFAdjust4x4Cr[0][0][0]),&(img->fadjust4x4Cr[0][1 + mode == I16MB][0][0]),MB_PIXELS * sizeof(int));
-        memcpy(&(bestIntraFAdjust4x4Cr[1][0][0]),&(img->fadjust4x4Cr[1][1 + mode == I16MB][0][0]),MB_PIXELS * sizeof(int));
-      }
-    }
-  }
-  if ( (params->yuv_format == YUV420 || params->yuv_format == YUV422) && (params->AdaptRndChroma))  
-  {
-    if (currMB->luma_transform_size_8x8_flag && mode == P8x8)
-    {
-      for (j = 0; j < img->mb_cr_size_y; j++)
-      {
-        memcpy(bestInterFAdjust4x4Cr[0][j],img->fadjust8x8Cr[0][0][j],img->mb_cr_size_x * sizeof(int));
-        memcpy(bestInterFAdjust4x4Cr[1][j],img->fadjust8x8Cr[1][0][j],img->mb_cr_size_x * sizeof(int));
-      }
-    }
-    else if (mode == P8x8)
-    {
-      for (j = 0; j < img->mb_cr_size_y; j++)
-      {
-        memcpy(bestInterFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][2][j],img->mb_cr_size_x * sizeof(int));
-        memcpy(bestInterFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][2][j],img->mb_cr_size_x * sizeof(int));
-      }
-    }
-    else if (is_inter)
-    {
-      for (j = 0; j < img->mb_cr_size_y; j++)
-      {
-        memcpy(bestInterFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][0][j],img->mb_cr_size_x * sizeof(int));
-        memcpy(bestInterFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][0][j],img->mb_cr_size_x * sizeof(int));
-      }
-    }
-    else
-    {
-      for (j = 0; j < img->mb_cr_size_y; j++)
-      {
-        memcpy(bestIntraFAdjust4x4Cr[0][j],img->fadjust4x4Cr[0][1][j],img->mb_cr_size_x * sizeof(int));
-        memcpy(bestIntraFAdjust4x4Cr[1][j],img->fadjust4x4Cr[1][1][j],img->mb_cr_size_x * sizeof(int));
-      }
-    }
-  }
-}
 
 /*!
  *************************************************************************************
@@ -1795,18 +1622,17 @@ void store_adaptive_rounding_parameters (Macroblock *currMB, int mode)
  */
 void store_macroblock_parameters (Macroblock *currMB, int mode)
 {
-  int  i, j, k, ****i4p, ***i3p;
-  int        bframe   = (img->type==B_SLICE);
+  int  j, ****i4p, ***i3p;
+  int  bframe   = (img->type==B_SLICE);
 
   //--- store best mode ---
   best_mode = mode;
   best_c_imode = currMB->c_ipred_mode;
   best_i16offset = img->i16offset;
 
-  // If condition is not really necessary.
-  bi_pred_me = (mode == 1) ? currMB->bi_pred_me : 0;
-
+  
   memcpy(b8mode, currMB->b8mode, BLOCK_MULTIPLE * sizeof(short));
+  memcpy(b8bipred_me, currMB->bipred_me, BLOCK_MULTIPLE * sizeof(short));
   memcpy(b8pdir, currMB->b8pdir, BLOCK_MULTIPLE * sizeof(short));
   memcpy(b4_intra_pred_modes,currMB->intra_pred_modes, MB_BLOCK_PARTITIONS * sizeof(char));
   memcpy(b8_intra_pred_modes8x8,currMB->intra_pred_modes8x8, MB_BLOCK_PARTITIONS * sizeof(char));
@@ -1859,17 +1685,9 @@ void store_macroblock_parameters (Macroblock *currMB, int mode)
   }
 
   //--- store results of decoders ---
-  if (params->rdopt==3 && img->type!=B_SLICE)
+  if (params->rdopt == 3 && img->type!=B_SLICE)
   {
-    for (k = 0; k<params->NoOfDecoders; k++)
-    {
-      for (j=img->pix_y; j<img->pix_y+16; j++)
-        for (i=img->pix_x; i<img->pix_x+16; i++)
-        {
-          // Keep the decoded values of each MB for updating the ref frames
-          decs->decY_best[k][j][i] = decs->decY[k][j][i];
-        }
-    }
+    errdo_store_best_block(img, decs->dec_mbY, enc_picture->p_dec_img[0], 0, 0, MB_BLOCK_SIZE);
   }
 
   //--- coeff, cbp, kac ---
@@ -1894,12 +1712,12 @@ void store_macroblock_parameters (Macroblock *currMB, int mode)
 
 
   for (j = 0; j<4; j++)
-    memcpy(l0_refframe[j],&enc_picture->ref_idx[LIST_0][img->block_y+j][img->block_x], BLOCK_MULTIPLE * sizeof(char));
+    memcpy(l0_refframe[j],&enc_picture->motion.ref_idx[LIST_0][img->block_y+j][img->block_x], BLOCK_MULTIPLE * sizeof(char));
 
   if (bframe)
   {
     for (j = 0; j<4; j++)
-      memcpy(l1_refframe[j],&enc_picture->ref_idx[LIST_1][img->block_y+j][img->block_x], BLOCK_MULTIPLE * sizeof(char));
+      memcpy(l1_refframe[j],&enc_picture->motion.ref_idx[LIST_1][img->block_y+j][img->block_x], BLOCK_MULTIPLE * sizeof(char));
   }
 }
 
@@ -1920,7 +1738,7 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
   int         i, j, k, ****i4p, ***i3p;
   int         block_x, block_y;
   char    **ipredmodes = img->ipredmode;
-  short   *cur_mv;
+  short   *cur_mv, total_bipred_me;
 
   //===== reconstruction values =====
 
@@ -2017,6 +1835,8 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
 
   memcpy(currMB->b8mode,b8mode, BLOCK_MULTIPLE * sizeof(short));
   memcpy(currMB->b8pdir,b8pdir, BLOCK_MULTIPLE * sizeof(short));
+  memcpy(currMB->bipred_me,b8bipred_me, BLOCK_MULTIPLE * sizeof(short));
+
 
   if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
   {
@@ -2024,9 +1844,6 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
     memcpy(rdopt->b8pdir,b8pdir, BLOCK_MULTIPLE * sizeof(short));
   }
 
-  currMB->bi_pred_me = currMB->mb_type == 1 ? bi_pred_me : 0;
-
-
   //if P8x8 mode and transform size 4x4 choosen, restore motion vector data for this transform size
   if (mode == P8x8 && !luma_transform_size_8x8_flag && params->Transform8x8Mode)
     RestoreMV8x8(1);
@@ -2051,10 +1868,9 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
 
   rdopt->luma_transform_size_8x8_flag  = currMB->luma_transform_size_8x8_flag;
 
-  if (params->rdopt==3 && img->type!=B_SLICE)
+  if (params->rdopt == 3 && img->type!=B_SLICE)  
   {
-    //! save the MB Mode of every macroblock
-    decs->dec_mb_mode[img->mb_y][img->mb_x] = mode;
+    errdo_get_best_block(img, enc_picture->p_dec_img[0], decs->dec_mbY, 0, MB_BLOCK_SIZE);
   }
 
   //==== reference frames =====
@@ -2069,26 +1885,24 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
       // backward prediction or intra
       if ((currMB->b8pdir[k] == 1) || IS_INTRA(currMB))
       {
-        enc_picture->ref_idx    [LIST_0][block_y][block_x]    = -1;
-        enc_picture->ref_pic_id [LIST_0][block_y][block_x]    = -1;
-        enc_picture->mv         [LIST_0][block_y][block_x][0] = 0;
-        enc_picture->mv         [LIST_0][block_y][block_x][1] = 0;
+        enc_picture->motion.ref_idx    [LIST_0][block_y][block_x]    = -1;
+        enc_picture->motion.ref_pic_id [LIST_0][block_y][block_x]    = -1;
+        enc_picture->motion.mv         [LIST_0][block_y][block_x][0] = 0;
+        enc_picture->motion.mv         [LIST_0][block_y][block_x][1] = 0;
 
         if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
           rdopt->refar[LIST_0][j][i] = -1;
       }
       else
       {
-        if (currMB->bi_pred_me && (currMB->b8pdir[k] == 2) && currMB->mb_type==1)
+        if (currMB->bipred_me[k] && (currMB->b8pdir[k] == 2) && is_bipred_enabled(currMB->mb_type))
         {
-          cur_mv = currMB->bi_pred_me == 1
-            ? img->bipred_mv1[LIST_0][0][currMB->b8mode[k]][j][i]
-            : img->bipred_mv2[LIST_0][0][currMB->b8mode[k]][j][i];
+          cur_mv = img->bipred_mv[currMB->bipred_me[k] - 1][LIST_0][0][currMB->b8mode[k]][j][i]; 
 
-          enc_picture->ref_idx    [LIST_0][block_y][block_x] = 0;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][0];
-          enc_picture->mv         [LIST_0][block_y][block_x][0] = cur_mv[0];
-          enc_picture->mv         [LIST_0][block_y][block_x][1] = cur_mv[1];
+          enc_picture->motion.ref_idx    [LIST_0][block_y][block_x] = 0;
+          enc_picture->motion.ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][0];
+          enc_picture->motion.mv         [LIST_0][block_y][block_x][0] = cur_mv[0];
+          enc_picture->motion.mv         [LIST_0][block_y][block_x][1] = cur_mv[1];
 
           if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
             rdopt->refar[LIST_0][j][i] = 0;
@@ -2096,9 +1910,9 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
         else
         {
           char cur_ref = l0_refframe[j][i];
-          enc_picture->ref_idx    [LIST_0][block_y][block_x] = cur_ref;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][(short)cur_ref];
-          memcpy(enc_picture->mv  [LIST_0][block_y][block_x], img->all_mv[LIST_0][(short)cur_ref][currMB->b8mode[k]][j][i], 2 * sizeof(short));
+          enc_picture->motion.ref_idx    [LIST_0][block_y][block_x] = cur_ref;
+          enc_picture->motion.ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + currMB->list_offset][(short)cur_ref];
+          memcpy(enc_picture->motion.mv  [LIST_0][block_y][block_x], img->all_mv[LIST_0][(short)cur_ref][currMB->b8mode[k]][j][i], 2 * sizeof(short));
 
           if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
             rdopt->refar[LIST_0][j][i] = cur_ref;
@@ -2108,10 +1922,10 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
       // forward prediction or intra
       if ((currMB->b8pdir[k] == 0) || IS_INTRA(currMB))
       {
-        enc_picture->ref_idx    [LIST_1][block_y][block_x]    = -1;
-        enc_picture->ref_pic_id [LIST_1][block_y][block_x]    = -1;
-        enc_picture->mv         [LIST_1][block_y][block_x][0] = 0;
-        enc_picture->mv         [LIST_1][block_y][block_x][1] = 0;
+        enc_picture->motion.ref_idx    [LIST_1][block_y][block_x]    = -1;
+        enc_picture->motion.ref_pic_id [LIST_1][block_y][block_x]    = -1;
+        enc_picture->motion.mv         [LIST_1][block_y][block_x][0] = 0;
+        enc_picture->motion.mv         [LIST_1][block_y][block_x][1] = 0;
 
         if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
           rdopt->refar[LIST_1][j][i] = -1;
@@ -2132,35 +1946,33 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
         // forward
         if (IS_INTRA(currMB)||(currMB->b8pdir[k] == 0))
         {
-          enc_picture->ref_idx    [LIST_1][block_y][block_x]    = -1;
-          enc_picture->ref_pic_id [LIST_1][block_y][block_x]    = -1;
-          enc_picture->mv         [LIST_1][block_y][block_x][0] = 0;
-          enc_picture->mv         [LIST_1][block_y][block_x][1] = 0;
+          enc_picture->motion.ref_idx    [LIST_1][block_y][block_x]    = -1;
+          enc_picture->motion.ref_pic_id [LIST_1][block_y][block_x]    = -1;
+          enc_picture->motion.mv         [LIST_1][block_y][block_x][0] = 0;
+          enc_picture->motion.mv         [LIST_1][block_y][block_x][1] = 0;
 
           if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
             rdopt->refar[LIST_1][j][i] = -1;
         }
         else
         {
-          if (currMB->bi_pred_me && (currMB->b8pdir[k] == 2) && currMB->mb_type==1)
+          if (currMB->bipred_me[k] && (currMB->b8pdir[k] == 2) && is_bipred_enabled(currMB->mb_type))
           {
-            cur_mv = currMB->bi_pred_me == 1
-              ? img->bipred_mv1[LIST_1][0][currMB->b8mode[k]][j][i]
-              : img->bipred_mv2[LIST_1][0][currMB->b8mode[k]][j][i];
+            cur_mv = img->bipred_mv[currMB->bipred_me[k] - 1][LIST_1][0][currMB->b8mode[k]][j][i]; 
 
-            enc_picture->ref_idx    [LIST_1][block_y][block_x] = 0;
-            enc_picture->ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + currMB->list_offset][0];
-            enc_picture->mv         [LIST_1][block_y][block_x][0] = cur_mv[0];
-            enc_picture->mv         [LIST_1][block_y][block_x][1] = cur_mv[1];
+            enc_picture->motion.ref_idx    [LIST_1][block_y][block_x] = 0;
+            enc_picture->motion.ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + currMB->list_offset][0];
+            enc_picture->motion.mv         [LIST_1][block_y][block_x][0] = cur_mv[0];
+            enc_picture->motion.mv         [LIST_1][block_y][block_x][1] = cur_mv[1];
 
             if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
               rdopt->refar[LIST_1][j][i] = 0;
           }
           else
           {
-            enc_picture->ref_idx    [LIST_1][block_y][block_x] = l1_refframe[j][i];
-            enc_picture->ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + currMB->list_offset][(short)l1_refframe[j][i]];
-            memcpy(enc_picture->mv  [LIST_1][block_y][block_x], img->all_mv[LIST_1][(short)l1_refframe[j][i]][currMB->b8mode[k]][j][i], 2 * sizeof(short));
+            enc_picture->motion.ref_idx    [LIST_1][block_y][block_x] = l1_refframe[j][i];
+            enc_picture->motion.ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + currMB->list_offset][(short)l1_refframe[j][i]];
+            memcpy(enc_picture->motion.mv  [LIST_1][block_y][block_x], img->all_mv[LIST_1][(short)l1_refframe[j][i]][currMB->b8mode[k]][j][i], 2 * sizeof(short));
 
             if (img->MbaffFrameFlag || (params->UseRDOQuant && params->RDOQ_QP_Num > 1))
               rdopt->refar[LIST_1][j][i] = l1_refframe[j][i];
@@ -2210,9 +2022,71 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
 
   //==== motion vectors =====
   SetMotionVectorsMB (currMB, bframe);
+  total_bipred_me  = 0;
+ 
+  for (i = 0; i < 4; i++)
+  {
+    total_bipred_me += currMB->bipred_me[i];
+  }
+
+  if (total_bipred_me && currMB->mb_type != 1)
+  {
+    UpdateMotionVectorPredictor(currMB);
+    //printf("new mode");
+  }
+  
 }
 
+/*!
+ *************************************************************************************
+ * \brief
+ *    Update motion vector predictors if biprediction mode is selected (B_SLICE only)
+ *************************************************************************************
+ */
+void UpdateMotionVectorPredictor(Macroblock* currMB) 
+{
+  int v = 0, h = 0, block_x, block_y, list, i, ref;
+  short * pred_mv;
+  int   parttype  = (currMB->mb_type<4?currMB->mb_type:4);
+  int   bsx       = params->blc_size[parttype][0];
+  int   bsy       = params->blc_size[parttype][1];
+  int   step_h    = (params->part_size[parttype][0]);
+  int   step_v    = (params->part_size[parttype][1]);
+  
+  for (i = 0; i < 4; i++)
+  {
+    if (currMB->bipred_me[i])
+    {
+      v = i >> 1;
+      h = i & 0x01;
+      break;
+    }
+  }
 
+  while(1)
+  {
+        block_x = img->block_x + h;
+        block_y = img->block_y + v;
+        for (list = 0; list < 2; list++)
+        {
+          ref = enc_picture->motion.ref_idx[list][block_y][block_x];
+          ref = (ref < 0 )? 0 : ref;
+          pred_mv = img->pred_mv[list][ref][parttype][v][h];
+          SetMotionVectorPredictor (currMB, pred_mv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, h << 2, v << 2, bsx, bsy);
+        }
+       
+       v += step_v;
+       h += step_h;
+       if (v >= 4 && h >= 4)
+         break;
+       if (v >= 4)
+         v = 0;
+       if (h >= 4)
+         h = 0;
+  }
+  
+}
+ 
 
 /*!
  *************************************************************************************
@@ -2220,9 +2094,9 @@ void set_stored_macroblock_parameters (Macroblock *currMB)
  *    Set reference frames and motion vectors
  *************************************************************************************
  */
-void SetRefAndMotionVectors (Macroblock *currMB, int block, int mode, int pdir, int fwref, int bwref)
+void SetRefAndMotionVectors (Macroblock *currMB, int block, int mode, int pdir, int fwref, int bwref, short bipred_me)
 {
-  int     i, j=0;
+  int     k, i, j=0;
   int     bslice  = (img->type==B_SLICE);
   int     pmode   = (mode==1||mode==2||mode==3?mode:4);
   int     j0      = ((block >> 1)<<1);
@@ -2231,108 +2105,174 @@ void SetRefAndMotionVectors (Macroblock *currMB, int block, int mode, int pdir,
   int     i1      = i0 + (params->part_size[pmode][0]);
   int     block_x, block_y;
   short   *cur_mv;
+  int64 ref_pic_num;
+  char *ref_idx;
 
-  if (pdir<0)
+  if (pdir < 0)
   {
-    for (j = img->block_y + j0; j < img->block_y + j1; j++)
+    for (k = LIST_0; k <= LIST_1; k++)
     {
-      for (i=img->block_x + i0; i<img->block_x +i1; i++)
+      for (j = img->block_y + j0; j < img->block_y + j1; j++)
       {
-        enc_picture->ref_pic_id[LIST_0][j][i] = -1;
-        enc_picture->ref_pic_id[LIST_1][j][i] = -1;
+        for (i=img->block_x + i0; i<img->block_x +i1; i++)
+          enc_picture->motion.ref_pic_id[k][j][i] = -1;
+
+        memset(&enc_picture->motion.ref_idx[k][j][img->block_x + i0], -1, (params->part_size[pmode][0]) * sizeof(char));
+        memset(enc_picture->motion.mv      [k][j][img->block_x + i0], 0, 2*(params->part_size[pmode][0]) * sizeof(short));
       }
-      memset(&enc_picture->ref_idx[LIST_0][j][img->block_x + i0], -1, (params->part_size[pmode][0]) * sizeof(char));
-      memset(&enc_picture->ref_idx[LIST_1][j][img->block_x + i0], -1, (params->part_size[pmode][0]) * sizeof(char));
-      memset(enc_picture->mv[LIST_0][j][img->block_x + i0], 0, 2*(params->part_size[pmode][0]) * sizeof(short));
-      memset(enc_picture->mv[LIST_1][j][img->block_x + i0], 0, 2*(params->part_size[pmode][0]) * sizeof(short));
     }
     return;
   }
 
   if (!bslice)
   {
-    for (j=j0; j<j1; j++)
+    int64 ref_pic_num = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][fwref];
+    for (j = j0; j < j1; j++)
     {
       block_y = img->block_y + j;
-      memset(&enc_picture->ref_idx   [LIST_0][block_y][img->block_x + i0], fwref, (params->part_size[pmode][0]) * sizeof(char));
-      for (i=i0; i<i1; i++)
-      {
-        block_x = img->block_x + i;
-        memcpy(enc_picture->mv [LIST_0][block_y][block_x], img->all_mv   [LIST_0][fwref][mode][j][i], 2 * sizeof(short));
-        enc_picture->ref_pic_id[LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][fwref];
-      }
+      for (block_x = img->block_x + i0; block_x < img->block_x + i1; block_x++)
+        enc_picture->motion.ref_pic_id[LIST_0][block_y][block_x] = ref_pic_num;
+
+      memset(&enc_picture->motion.ref_idx[LIST_0][block_y][img->block_x + i0], fwref, (params->part_size[pmode][0]) * sizeof(char));
+      memcpy(enc_picture->motion.mv      [LIST_0][block_y][img->block_x + i0], img->all_mv[LIST_0][fwref][mode][j][i0], 2 * (i1 - i0) * sizeof(short));
     }
     return;
   }
-  else
+  else //bslice
   {
-    for (j=j0; j<j1; j++)
+    if ((pdir == 0 || pdir == 2))
     {
-      block_y = img->block_y + j;
-      for (i=i0; i<i1; i++)
+      if (bipred_me && (pdir == 2) && is_bipred_enabled(mode))
       {
-        block_x = img->block_x + i;
-        if (mode==0)
-        {
-          pdir  = direct_pdir[block_y][block_x];
-          fwref = direct_ref_idx[LIST_0][block_y][block_x];
-          bwref = direct_ref_idx[LIST_1][block_y][block_x];
-        }
-
-        if ((pdir==0 || pdir==2))
+        for (j=j0; j<j1; j++)
         {
-          if (currMB->bi_pred_me && (pdir == 2) && mode == 1)
+          block_y = img->block_y + j;
+          for (i=i0; i<i1; i++)
           {
-            cur_mv = currMB->bi_pred_me == 1
-              ? img->bipred_mv1[LIST_0][0][mode][j][i]
-              : img->bipred_mv2[LIST_0][0][mode][j][i];
-
-            enc_picture->mv        [LIST_0][block_y][block_x][0] = cur_mv[0];
-            enc_picture->mv        [LIST_0][block_y][block_x][1] = cur_mv[1];
-            enc_picture->ref_idx   [LIST_0][block_y][block_x]    = 0;
-            enc_picture->ref_pic_id[LIST_0][block_y][block_x]    = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][0];
+            block_x = img->block_x + i;
+
+            cur_mv = img->bipred_mv[bipred_me - 1][LIST_0][0][mode][j][i]; 
+
+              enc_picture->motion.mv        [LIST_0][block_y][block_x][0] = cur_mv[0];
+              enc_picture->motion.mv        [LIST_0][block_y][block_x][1] = cur_mv[1];
+              enc_picture->motion.ref_idx   [LIST_0][block_y][block_x]    = 0;
+              enc_picture->motion.ref_pic_id[LIST_0][block_y][block_x]    = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][0];
           }
-          else
+        }
+      }
+      else
+      {
+        if (mode==0)
+        {
+          for (j=j0; j<j1; j++)
           {
-            memcpy(enc_picture->mv [LIST_0][block_y][block_x], img->all_mv[LIST_0][fwref][mode][j][i], 2 * sizeof(short));
-            enc_picture->ref_idx   [LIST_0][block_y][block_x] = fwref;
-            enc_picture->ref_pic_id[LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][(short)enc_picture->ref_idx[LIST_0][block_y][block_x]];
+            block_y = img->block_y + j;
+            ref_idx = enc_picture->motion.ref_idx[LIST_0][block_y];
+            memcpy(&ref_idx[img->block_x + i0], &direct_ref_idx[LIST_0][block_y][img->block_x + i0], (i1 - i0) * sizeof(char));
+            memcpy(&enc_picture->motion.mv[LIST_0][block_y][img->block_x + i0][0], img->all_mv[LIST_0][fwref][mode][j][i0], 2 * (i1 - i0) * sizeof(short));
+            for (block_x = img->block_x + i0; block_x < img->block_x + i1; block_x++)
+            {              
+              enc_picture->motion.ref_pic_id[LIST_0][block_y][block_x] = 
+                enc_picture->ref_pic_num[LIST_0+currMB->list_offset][(short)ref_idx[block_x]];
+            }            
           }
         }
         else
         {
-          enc_picture->mv        [LIST_0][block_y][block_x][0] = 0;
-          enc_picture->mv        [LIST_0][block_y][block_x][1] = 0;
-          enc_picture->ref_idx   [LIST_0][block_y][block_x]    = -1;
-          enc_picture->ref_pic_id[LIST_0][block_y][block_x]    = -1;
+          for (j=j0; j<j1; j++)
+          {
+            block_y = img->block_y + j;
+            ref_pic_num = enc_picture->ref_pic_num[LIST_0+currMB->list_offset][fwref];
+            memcpy(&enc_picture->motion.mv[LIST_0][block_y][img->block_x + i0][0], img->all_mv[LIST_0][fwref][mode][j][i0], 2 * (i1 - i0) * sizeof(short));
+            memset(&enc_picture->motion.ref_idx[LIST_0][block_y][img->block_x + i0], fwref, (i1 - i0) * sizeof(char));
+            for (block_x = img->block_x + i0; block_x < img->block_x + i1; block_x++)
+            {              
+              enc_picture->motion.ref_pic_id[LIST_0][block_y][block_x] = ref_pic_num ;
+            }
+          }
         }
+      }  
+    }
+    else
+    {
+      for (j=j0; j<j1; j++)
+      {
+        block_y = img->block_y + j;
+        for (i=img->block_x + i0; i<img->block_x +i1; i++)
+          enc_picture->motion.ref_pic_id[LIST_0][block_y][i] = -1;
 
-        if ((pdir==1 || pdir==2))
+        memset(&enc_picture->motion.ref_idx[LIST_0][block_y][img->block_x + i0], -1, (i1 - i0) * sizeof(char));
+        memset(enc_picture->motion.mv[LIST_0][block_y][img->block_x + i0], 0, 2 * (i1 - i0) * sizeof(short));
+      }
+    }
+
+
+    if ((pdir==1 || pdir==2))
+    {
+
+      if (bipred_me && (pdir == 2) && is_bipred_enabled(mode))
+      {
+        for (j=j0; j<j1; j++)
         {
-          if (currMB->bi_pred_me && (pdir == 2) && mode == 1)
+          block_y = img->block_y + j;
+
+          for (i=i0; i<i1; i++)
           {
-            cur_mv = currMB->bi_pred_me == 1
-              ? img->bipred_mv1[LIST_1][0][mode][j][i]
-              : img->bipred_mv2[LIST_1][0][mode][j][i];
-
-            enc_picture->mv        [LIST_1][block_y][block_x][0] = cur_mv[0];
-            enc_picture->mv        [LIST_1][block_y][block_x][1] = cur_mv[1];
-            enc_picture->ref_idx   [LIST_1][block_y][block_x]    = 0;
-            enc_picture->ref_pic_id[LIST_1][block_y][block_x]    = enc_picture->ref_pic_num[LIST_1+currMB->list_offset][0];
+            block_x = img->block_x + i;
+
+            cur_mv = img->bipred_mv[bipred_me - 1][LIST_1][0][mode][j][i]; 
+
+              enc_picture->motion.mv        [LIST_1][block_y][block_x][0] = cur_mv[0];
+              enc_picture->motion.mv        [LIST_1][block_y][block_x][1] = cur_mv[1];
+              enc_picture->motion.ref_idx   [LIST_1][block_y][block_x]    = 0;
+              enc_picture->motion.ref_pic_id[LIST_1][block_y][block_x]    = enc_picture->ref_pic_num[LIST_1+currMB->list_offset][0];
           }
-          else
+        }
+      }
+      else
+      {
+        if (mode==0)
+        {
+          for (j=j0; j<j1; j++)
           {
-            memcpy(enc_picture->mv [LIST_1][block_y][block_x], img->all_mv[LIST_1][bwref][mode][j][i], 2 * sizeof(short));
-            enc_picture->ref_idx   [LIST_1][block_y][block_x] = bwref;
-            enc_picture->ref_pic_id[LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1+currMB->list_offset][(short)enc_picture->ref_idx[LIST_1][block_y][block_x]];
+            block_y = img->block_y + j;
+
+            ref_idx = enc_picture->motion.ref_idx[LIST_1][block_y];
+            memcpy(&ref_idx[img->block_x + i0], &direct_ref_idx[LIST_1][block_y][img->block_x + i0], (i1 - i0) * sizeof(char));            
+            memcpy(&enc_picture->motion.mv[LIST_1][block_y][img->block_x + i0][0], img->all_mv[LIST_1][(int) ref_idx[img->block_x + i0]][mode][j][i0], 2 * (i1 - i0) * sizeof(short));
+            for (i=i0; i<i1; i++)
+            {
+              block_x = img->block_x + i;
+              enc_picture->motion.ref_pic_id[LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1+currMB->list_offset][(short)ref_idx[block_x]];
+            }            
           }
         }
         else
         {
-          enc_picture->mv        [LIST_1][block_y][block_x][0] = 0;
-          enc_picture->mv        [LIST_1][block_y][block_x][1] = 0;
-          enc_picture->ref_idx   [LIST_1][block_y][block_x]    = -1;
-          enc_picture->ref_pic_id[LIST_1][block_y][block_x]    = -1;
+          for (j=j0; j<j1; j++)
+          {
+            block_y = img->block_y + j;
+            ref_pic_num = enc_picture->ref_pic_num[LIST_1+currMB->list_offset][bwref];
+            memcpy(&enc_picture->motion.mv[LIST_1][block_y][img->block_x + i0][0], img->all_mv[LIST_1][bwref][mode][j][i0], 2 * (i1 - i0) * sizeof(short));
+            memset(&enc_picture->motion.ref_idx[LIST_1][block_y][img->block_x + i0], bwref, (i1 - i0) * sizeof(char));
+            for (block_x = img->block_x + i0; block_x < img->block_x + i1; block_x++)
+            {
+              enc_picture->motion.ref_pic_id[LIST_1][block_y][block_x] = ref_pic_num ;
+            }
+          }
+        }
+      }  
+    }
+    else
+    {
+      for (j=j0; j<j1; j++)
+      {
+        block_y = img->block_y + j;
+        memset(enc_picture->motion.mv[LIST_1][block_y][img->block_x + i0], 0, 2 * (i1 - i0) * sizeof(short));
+        memset(&enc_picture->motion.ref_idx[LIST_1][block_y][img->block_x + i0], -1, (i1 - i0)  * sizeof(char));
+        for (block_x = img->block_x + i0; block_x < img->block_x + i1; block_x++)
+        {
+          enc_picture->motion.ref_pic_id[LIST_1][block_y][block_x]    = -1;
         }
       }
     }
@@ -2666,12 +2606,12 @@ int GetBestTransformP8x8()
     mb_x = (block8x8 & 0x01) << 3;
     //===== loop over 4x4 blocks =====
     k=0;
-    for (block_y=mb_y; block_y<mb_y+8; block_y+=4)
+    for (block_y = mb_y; block_y < mb_y + 8; block_y += 4)
     {
       pic_pix_y = img->opix_y + block_y;
 
       //get cost for transform size 4x4
-      for (block_x=mb_x; block_x<mb_x+8; block_x+=4)
+      for (block_x = mb_x; block_x<mb_x + 8; block_x += 4)
       {
         pic_pix_x = img->opix_x + block_x;
 
@@ -2749,15 +2689,14 @@ void set_mbaff_parameters(Macroblock  *currMB)
   {
     for (j = 0; j < BLOCK_MULTIPLE; j++)
     {
-      memcpy(rdopt->refar[LIST_0][j],&enc_picture->ref_idx[LIST_0][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
-      memcpy(rdopt->refar[LIST_1][j],&enc_picture->ref_idx[LIST_1][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
+      memcpy(rdopt->refar[LIST_0][j],&enc_picture->motion.ref_idx[LIST_0][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
+      memcpy(rdopt->refar[LIST_1][j],&enc_picture->motion.ref_idx[LIST_1][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
     }
-    rdopt->bi_pred_me = currMB->bi_pred_me;
   }
   else
   {
     for (j = 0; j < BLOCK_MULTIPLE; j++)
-      memcpy(rdopt->refar[LIST_0][j],&enc_picture->ref_idx[LIST_0][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
+      memcpy(rdopt->refar[LIST_0][j],&enc_picture->motion.ref_idx[LIST_0][img->block_y + j][img->block_x] , BLOCK_MULTIPLE * sizeof(char));
   }
 
   memcpy(rdopt->intra_pred_modes,currMB->intra_pred_modes, MB_BLOCK_PARTITIONS * sizeof(char));
@@ -2790,303 +2729,137 @@ void reset_coding_state_cs_cm(Macroblock *currMB)
   reset_coding_state(currMB, cs_cm);
 }
 
-/*!
-************************************************************************
-* \brief
-*    update rounding offsets based on JVT-N011
-************************************************************************
-*/
-void update_offset_params(Macroblock *currMB, int mode, int luma_transform_size_8x8_flag)
-{
-  int is_inter = (mode != I4MB)&&(mode != I16MB) && (mode != I8MB);
-  int luma_pos = AdaptRndPos[(is_inter<<1) + luma_transform_size_8x8_flag][img->type];
-  int i,j;
-  int qp = currMB->qp + img->bitdepth_luma_qp_scale - MIN_QP;
-  int cur_qp = params->AdaptRoundingFixed ? 0 : qp;
-  int temp = 0;
-  int offsetRange = 1 << (OffsetBits - 1);
-  int blk_mask = 0x03 + (luma_transform_size_8x8_flag<<2);
-  int blk_shift = 2 + luma_transform_size_8x8_flag;
-  short **offsetList = luma_transform_size_8x8_flag ? OffsetList8x8[cur_qp] : OffsetList4x4[cur_qp];
-
-  int **fAdjust = is_inter
-    ? (luma_transform_size_8x8_flag ? bestInterFAdjust8x8 : bestInterFAdjust4x4)
-    : (luma_transform_size_8x8_flag ? bestIntraFAdjust8x8 : bestIntraFAdjust4x4);
-
-  if( (active_sps->chroma_format_idc == YUV444)&&IS_INDEPENDENT(params) )
-  {
-    if( luma_transform_size_8x8_flag )  // 8x8
-      luma_pos += 5 * img->colour_plane_id;
-    else  // 4x4
-      luma_pos += img->colour_plane_id;
-  }
-
-  for (j=0; j < MB_BLOCK_SIZE; j++)
-  {
-    int j_pos = ((j & blk_mask)<<blk_shift);
-    for (i=0; i < MB_BLOCK_SIZE; i++)
-    {
-      temp = j_pos + (i & blk_mask);
-      offsetList[luma_pos][temp] += fAdjust[j][i];
-      offsetList[luma_pos][temp]  = iClip3(0, offsetRange, offsetList[luma_pos][temp]);
-    }
-  }
-
-  if(img->P444_joined)
-  { 
-    int ***fAdjustCbCr = (int ***) (is_inter
-      ? (luma_transform_size_8x8_flag ? bestInterFAdjust8x8Cr : bestInterFAdjust4x4Cr)
-      : (luma_transform_size_8x8_flag ? bestIntraFAdjust8x8Cr : bestIntraFAdjust4x4Cr));
-    int uv;
-
-    for(uv=0; uv<2; uv++)
-    {
-      luma_pos = AdaptRndPos[(is_inter<<1) + luma_transform_size_8x8_flag][img->type];
-      if(luma_transform_size_8x8_flag )  // 8x8
-        luma_pos += 5 * (uv+1);
-      else  // 4x4
-        luma_pos += (uv+1);
-      for (j=0; j < MB_BLOCK_SIZE; j++)
-      {
-        int j_pos = ((j & blk_mask)<<blk_shift);
-        for (i=0; i < MB_BLOCK_SIZE; i++)
-        {
-          temp = j_pos + (i & blk_mask);
-          offsetList[luma_pos][temp] += fAdjustCbCr[uv][j][i];
-          offsetList[luma_pos][temp] = iClip3(0,offsetRange,offsetList[luma_pos][temp]);
-        }
-      }
-    }
-  }
-
-  if ((params->yuv_format == YUV420 || params->yuv_format == YUV422 )&&(params->AdaptRndChroma))
-  {
-    int u_pos = AdaptRndCrPos[is_inter][img->type];
-    int v_pos = u_pos + 1;
-    int jpos;
-
-    int ***fAdjustCr = is_inter ? bestInterFAdjust4x4Cr : bestIntraFAdjust4x4Cr;
-
-    for (j = 0; j < img->mb_cr_size_y; j++)
-    {
-      jpos = ((j & 0x03)<<2);
-      for (i = 0; i < img->mb_cr_size_x; i++)
-      {
-        temp = jpos + (i & 0x03);
-        OffsetList4x4[cur_qp][u_pos][temp] += fAdjustCr[0][j][i];
-        OffsetList4x4[cur_qp][u_pos][temp] = iClip3(0,offsetRange,OffsetList4x4[cur_qp][u_pos][temp]);
-        OffsetList4x4[cur_qp][v_pos][temp] += fAdjustCr[1][j][i];
-        OffsetList4x4[cur_qp][v_pos][temp] = iClip3(0,offsetRange,OffsetList4x4[cur_qp][v_pos][temp]);
-      }
-    }
-  }
-}
-
-void assign_enc_picture_params(int mode, char best_pdir, int block, int list_offset, int best_l0_ref, int best_l1_ref, int bframe)
+void assign_enc_picture_params(int mode, char best_pdir, int block, int list_offset, int best_l0_ref, int best_l1_ref, int bframe, short bipred_me)
 {
   int i,j;
   int block_x, block_y;
-  short *cur_mv;
-
-  if (mode==1)
+  int list, maxlist, bestref;
+  short ***curr_mv = NULL;
+  int64 curr_ref_idx = 0;
+ 
+  int start_x = 0, start_y = 0, end_x = BLOCK_MULTIPLE, end_y = BLOCK_MULTIPLE; 
+  switch (mode)
   {
-    if (best_pdir==1)
-    {
-      for (j=img->block_y+(block&2); j<img->block_y+(block&2) + BLOCK_MULTIPLE; j++)
-      {
-        block_x = img->block_x+(block&1)*2;
-
-        memset(&enc_picture->ref_idx[LIST_0][j][block_x], -1 ,     BLOCK_MULTIPLE * sizeof(char));
-        memset(enc_picture->mv      [LIST_0][j][block_x],  0 , 2 * BLOCK_MULTIPLE * sizeof(short));
-        for (i=block_x; i<block_x + BLOCK_MULTIPLE; i++)
-        {
-          enc_picture->ref_pic_id [LIST_0][j][i]    = -1;
-        }
-      }
-    }
-    else if (img->bi_pred_me[mode])
+    case 1:
+      start_x = 0;
+      start_y = 0;
+      end_x   = BLOCK_MULTIPLE;
+      end_y   = BLOCK_MULTIPLE;
+      break;
+    case 2:
+      start_x = 0;
+      start_y = block * 2;
+      end_x   = BLOCK_MULTIPLE;
+      end_y   = (block + 1) * 2;
+      break;
+    case 3:
+      start_x = block * 2;
+      start_y = 0;
+      end_x   = (block + 1) * 2;
+      end_y   = BLOCK_MULTIPLE;
+      break;
+    default:
+      break;
+  }
+
+  maxlist  = bframe ? 1: 0;
+  for (list = 0; list <= maxlist; list++)
+  {
+    bestref = (list == 0) ? best_l0_ref : best_l1_ref;
+    switch (bipred_me)
+    {
+      case 0:
+        curr_mv = img->all_mv[list][bestref][mode];
+        curr_ref_idx = enc_picture->ref_pic_num[list + list_offset][bestref];
+        break;
+      case 1:
+        curr_mv = img->bipred_mv[0][list][0][mode] ; //best_l0_ref has to be zero in this case
+        curr_ref_idx = enc_picture->ref_pic_num[list + list_offset][0];
+        break;
+      case 2:
+        curr_mv = img->bipred_mv[1][list][0][mode] ; //best_l0_ref has to be zero in this case
+        curr_ref_idx = enc_picture->ref_pic_num[list + list_offset][0];
+        break;
+      default:
+        break;
+    }
+
+    for (j = start_y; j < end_y; j++)
     {
-      for (j=0; j<BLOCK_MULTIPLE; j++)
+      block_y = img->block_y + j;
+      for (i = start_x; i < end_x; i++)
       {
-        block_y = img->block_y+(block&2)+j;
-        block_x = img->block_x+(block&1)*2;
-        memset(&enc_picture->ref_idx[LIST_0][block_y][block_x], 0, BLOCK_MULTIPLE * sizeof(char));
-        for (i=0; i<BLOCK_MULTIPLE; i++)
+        block_x = img->block_x + i;
+        if ((best_pdir != 2) && (best_pdir != list))
         {
-          cur_mv = img->bi_pred_me[mode] == 1
-            ? img->bipred_mv1[LIST_0][0][mode][i][j]
-            : img->bipred_mv2[LIST_0][0][mode][i][j];
-
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x + i]    = enc_picture->ref_pic_num[LIST_0 + list_offset][0];
-          enc_picture->mv         [LIST_0][block_y][block_x + i][0] = cur_mv[0];
-          enc_picture->mv         [LIST_0][block_y][block_x + i][1] = cur_mv[1];
+            enc_picture->motion.ref_idx    [list][block_y][block_x]    = -1;
+            enc_picture->motion.ref_pic_id [list][block_y][block_x]    = -1;
+            enc_picture->motion.mv         [list][block_y][block_x][0] = 0;
+            enc_picture->motion.mv         [list][block_y][block_x][1] = 0;
         }
-      }
-    }
-    else
-    {
-      for (j=0; j<BLOCK_MULTIPLE; j++)
+        else
       {
-        block_y = img->block_y+(block&2)+j;
-        block_x = img->block_x+(block&1)*2;
-        memset(&enc_picture->ref_idx[LIST_0][block_y][block_x], best_l0_ref , BLOCK_MULTIPLE * sizeof(char));
-        for (i=0; i<BLOCK_MULTIPLE; i++)
-        {
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x + i]    = enc_picture->ref_pic_num[LIST_0 + list_offset][best_l0_ref];
-          memcpy(enc_picture->mv  [LIST_0][block_y][block_x + i], img->all_mv[LIST_0][best_l0_ref][mode][j][i], 2 * sizeof(short));
+          enc_picture->motion.ref_pic_id [list][block_y][block_x]    = curr_ref_idx;
+          enc_picture->motion.mv         [list][block_y][block_x][0] = curr_mv[j][i][0];
+          enc_picture->motion.mv         [list][block_y][block_x][1] = curr_mv[j][i][1];
         }
       }
     }
+  }
+}
 
-    if (bframe)
-    {
-      if (best_pdir==0)
-      {
-        for (j=img->block_y+(block&2); j<img->block_y+(block&2) + BLOCK_MULTIPLE; j++)
-        {
-          block_x = img->block_x+(block&1)*2;
-          memset(&enc_picture->ref_idx[LIST_1][j][block_x], -1 , BLOCK_MULTIPLE * sizeof(char));
-          memset(enc_picture->mv[LIST_1][j][block_x], 0 , 2 * BLOCK_MULTIPLE * sizeof(short));
-          for (i=block_x; i<block_x + BLOCK_MULTIPLE; i++)
-          {
-            enc_picture->ref_pic_id [LIST_1][j][i] = -1;
-          }
-        }
-      }
-      else
-      {
-        if (img->bi_pred_me[mode])
-        {
-          for (j=0; j<BLOCK_MULTIPLE; j++)
-          {
-            block_y = img->block_y+(block&2)+j;
-            block_x = img->block_x+(block&1)*2;
-            memset(&enc_picture->ref_idx[LIST_1][block_y][block_x], 0, BLOCK_MULTIPLE * sizeof(char));
-            for (i=0; i<BLOCK_MULTIPLE; i++)
-            {
-              cur_mv = (img->bi_pred_me[mode] == 1)
-                ? img->bipred_mv1[LIST_1][0][mode][i][j]
-                : img->bipred_mv2[LIST_1][0][mode][i][j];
-
-              enc_picture->ref_pic_id [LIST_1][block_y][block_x + i] =
-                enc_picture->ref_pic_num[LIST_1 + list_offset][0];
-              enc_picture->mv         [LIST_1][block_y][block_x + i][0] = cur_mv[0];
-              enc_picture->mv         [LIST_1][block_y][block_x + i][1] = cur_mv[1];
-            }
-          }
-        }
-        else
-        {
-          for (j=0; j<BLOCK_MULTIPLE; j++)
-          {
-            block_y = img->block_y+(block&2)+j;
-            block_x = img->block_x+(block&1)*2;
-            memset(&enc_picture->ref_idx[LIST_1][block_y][block_x], best_l1_ref, BLOCK_MULTIPLE * sizeof(char));
-            for (i=0; i<BLOCK_MULTIPLE; i++)
-            {
 
-              if(best_l1_ref>=0)
-              {
-                enc_picture->ref_pic_id [LIST_1][block_y][block_x + i] = enc_picture->ref_pic_num[LIST_1 + list_offset][best_l1_ref];
-                memcpy(enc_picture->mv  [LIST_1][block_y][block_x + i], img->all_mv[LIST_1][best_l1_ref][mode][j][i], 2 * sizeof(short));
-              }
-              else
-              {
-                enc_picture->ref_pic_id [LIST_1][block_y][block_x + i] = enc_picture->ref_pic_num[LIST_1 + list_offset][0];
-              }
-            }
-          }
-        }
-      }
-    }
+/*!
+ *************************************************************************************
+ * \brief
+ *    Set block 8x8 mode information
+ *************************************************************************************
+ */
+void set_block8x8_info(Block8x8Info *b8x8info, int mode, int block,  char best_ref[2], char best_pdir, short bipred_me)
+{
+  int i;
+  //----- set reference frame and direction parameters -----
+  if (mode==3)
+  {
+    b8x8info->best8x8l0ref [3][block  ] = b8x8info->best8x8l0ref [3][  block+2] = best_ref[LIST_0];
+    b8x8info->best8x8pdir  [3][block  ] = b8x8info->best8x8pdir  [3][  block+2] = best_pdir;
+    b8x8info->best8x8l1ref [3][block  ] = b8x8info->best8x8l1ref [3][  block+2] = best_ref[LIST_1];
+    b8x8info->bipred8x8me  [3][block  ] = b8x8info->bipred8x8me  [3][block+2  ] = bipred_me;
   }
   else if (mode==2)
   {
-    for (j=0; j<2; j++)
-    {
-      block_y = img->block_y + block * 2 + j;
-      for (i=0; i<BLOCK_MULTIPLE; i++)
-      {
-        block_x = img->block_x + i;
-        if (best_pdir==1)
-        {
-          enc_picture->ref_idx    [LIST_0][block_y][block_x]    = -1;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x]    = -1;
-          enc_picture->mv         [LIST_0][block_y][block_x][0] = 0;
-          enc_picture->mv         [LIST_0][block_y][block_x][1] = 0;
-        }
-        else
-        {
-          enc_picture->ref_idx    [LIST_0][block_y][block_x] = best_l0_ref;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + list_offset][best_l0_ref];
-          memcpy(enc_picture->mv  [LIST_0][block_y][block_x], img->all_mv[LIST_0][best_l0_ref][mode][j+block*2][i], 2 * sizeof(short));
-        }
-
-        if (bframe)
-        {
-          if (best_pdir==0)
-          {
-            enc_picture->ref_idx    [LIST_1][block_y][block_x]    = -1;
-            enc_picture->ref_pic_id [LIST_1][block_y][block_x]    = -1;
-            memset(enc_picture->mv [LIST_1][block_y][block_x], 0, 2 * sizeof(short));
-          }
-          else
-          {
-            enc_picture->ref_idx[LIST_1][block_y][block_x] = best_l1_ref;
-            if(best_l1_ref>=0)
-            {
-              enc_picture->ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + list_offset][best_l1_ref];
-              memcpy(enc_picture->mv  [LIST_1][block_y][block_x], img->all_mv[LIST_1][best_l1_ref][mode][j+ block*2][i], 2 * sizeof(short));
-            }
-          }
-        }
-      }
-    }
+    b8x8info->best8x8l0ref [2][2*block] = b8x8info->best8x8l0ref [2][2*block+1] = best_ref[LIST_0];
+    b8x8info->best8x8pdir  [2][2*block] = b8x8info->best8x8pdir  [2][2*block+1] = best_pdir;
+    b8x8info->best8x8l1ref [2][2*block] = b8x8info->best8x8l1ref [2][2*block+1] = best_ref[LIST_1];
+    b8x8info->bipred8x8me  [2][2*block  ] = b8x8info->bipred8x8me[2][2*block+1  ] = bipred_me;
   }
   else
   {
-    for (j=0; j<BLOCK_MULTIPLE; j++)
-    {
-      block_y = img->block_y+j;
-      for (i=0; i<2; i++)
-      {
-        block_x = img->block_x + block*2 + i;
-        if (best_pdir==1)
-        {
-          enc_picture->ref_idx    [LIST_0][block_y][block_x]    = -1;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x]    = -1;
-          memset(enc_picture->mv  [LIST_0][block_y][block_x], 0, 2 * sizeof(short));
-        }
-        else
-        {
-          enc_picture->ref_idx    [LIST_0][block_y][block_x] = best_l0_ref;
-          enc_picture->ref_pic_id [LIST_0][block_y][block_x] = enc_picture->ref_pic_num[LIST_0 + list_offset][best_l0_ref];
-          memcpy(enc_picture->mv  [LIST_0][block_y][block_x], img->all_mv[LIST_0][best_l0_ref][mode][j][block*2+i], 2 * sizeof(short));
-        }
-
-        if (bframe)
-        {
-          if (best_pdir==0)
-          {
-            enc_picture->ref_idx    [LIST_1][block_y][block_x]    = -1;
-            enc_picture->ref_pic_id [LIST_1][block_y][block_x]    = -1;
-            memset(enc_picture->mv  [LIST_1][block_y][block_x], 0, 2 * sizeof(short));
-          }
-          else
-          {
-            enc_picture->ref_idx[LIST_1][block_y][block_x] = best_l1_ref;
-            if(best_l1_ref>=0)
-            {
-              enc_picture->ref_pic_id [LIST_1][block_y][block_x] = enc_picture->ref_pic_num[LIST_1 + list_offset][best_l1_ref];
-              memcpy(enc_picture->mv[LIST_1][block_y][block_x], img->all_mv[LIST_1][best_l1_ref][mode][j][block*2+i], 2 * sizeof(short));
-            }
-          }
-        }
-      }
-    }
+    memset(&b8x8info->best8x8l0ref [1][0], best_ref[LIST_0], 4 * sizeof(char));
+    memset(&b8x8info->best8x8l1ref [1][0], best_ref[LIST_1], 4 * sizeof(char));
+    memset(&b8x8info->best8x8pdir  [1][0], best_pdir, 4 * sizeof(char));
+    for (i = 0; i< 4; i++)
+      b8x8info->bipred8x8me  [1][i] =  bipred_me;
   }
 }
 
+/*!
+ *************************************************************************************
+ * \brief
+ *    Set block 8x8 mode information for P8x8 mode
+ *************************************************************************************
+ */
+void set_subblock8x8_info(Block8x8Info *b8x8info,int mode, int block, RD_8x8DATA *tr)
+{          
+  b8x8info->best8x8mode         [block] = tr->part8x8mode  [block];
+  b8x8info->best8x8pdir   [mode][block] = tr->part8x8pdir  [block];
+  b8x8info->best8x8l0ref  [mode][block] = tr->part8x8l0ref [block];
+  b8x8info->best8x8l1ref  [mode][block] = tr->part8x8l1ref [block];
+  b8x8info->bipred8x8me   [mode][block] = tr->part8x8bipred[block];
+}
+
+
+
 void update_refresh_map(int intra, int intra1, Macroblock *currMB)
 {
   if (params->RestrictRef==1)
@@ -3099,7 +2872,7 @@ void update_refresh_map(int intra, int intra1, Macroblock *currMB)
       refresh_map[2*img->mb_y+1][2*img->mb_x  ] = (intra ? 1 : 0);
       refresh_map[2*img->mb_y+1][2*img->mb_x+1] = (intra ? 1 : 0);
     }
-    else if (params->rdopt==3)
+    else if (params->rdopt == 3)
     {
       refresh_map[2*img->mb_y  ][2*img->mb_x  ] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
       refresh_map[2*img->mb_y  ][2*img->mb_x+1] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
@@ -3172,43 +2945,7 @@ void generate_pred_error(imgpel **cur_img, imgpel prd_img[16][16], imgpel cur_pr
   }        
 }
 
-void store_adaptive_rounding (int block_y, int block_x)
-{
-  int j;
 
-  for (j = block_y; j < block_y + 4; j++)
-    memcpy(&fadjust4x4[j][block_x],&img->fadjust4x4[1][j][block_x], BLOCK_SIZE * sizeof(int));
 
-  if (img->P444_joined)
-  {
-    for (j = block_y; j < block_y + 4; j++)
-    {
-      memcpy(&fadjust4x4Cr[0][j][block_x],&img->fadjust4x4Cr[0][1][j][block_x], BLOCK_SIZE * sizeof(int));
-    }
-    for (j = block_y; j < block_y + 4; j++)
-    {
-      memcpy(&fadjust4x4Cr[1][j][block_x],&img->fadjust4x4Cr[1][1][j][block_x], BLOCK_SIZE * sizeof(int));
-    }
-  }
-}
 
-void update_adaptive_rounding(int block_y, int block_x)
-{
-  int j;
-
-  for (j = block_y; j < block_y + BLOCK_SIZE; j++)
-    memcpy (&img->fadjust4x4[1][j][block_x],&fadjust4x4[j][block_x], BLOCK_SIZE * sizeof(int));
-
-  if (img->P444_joined)
-  {
-    for (j = 0; j < block_y + BLOCK_SIZE; j++)
-    {
-      memcpy (&img->fadjust4x4Cr[0][1][j][block_x],&fadjust4x4Cr[0][j][block_x], BLOCK_SIZE * sizeof(int));
-    }
-    for (j = 0; j < block_y + BLOCK_SIZE; j++)
-    {
-      memcpy (&img->fadjust4x4Cr[1][1][j][block_x],&fadjust4x4Cr[1][j][block_x], BLOCK_SIZE * sizeof(int));
-    }
-  }
-}
 
diff --git a/lencod/src/rdpicdecision.c b/lencod/src/rdpicdecision.c
index 3eed085..1d681b3 100644
--- a/lencod/src/rdpicdecision.c
+++ b/lencod/src/rdpicdecision.c
@@ -46,19 +46,16 @@ int picture_coding_decision (Picture *picture1, Picture *picture2, int qp)
   double lambda_picture;
   int spframe = (img->type == SP_SLICE);
   int bframe = (img->type == B_SLICE);
-  double snr_picture1, snr_picture2;
-  int bit_picture1, bit_picture2;
+  double sse_picture1, sse_picture2;
 
   if (params->successive_Bframe)
     lambda_picture = (qp < 20 ? 0.55 : 0.68) * pow (2, (qp - SHIFT_QP) / 3.0) * (bframe || spframe ? 2 : 1);
   else
     lambda_picture = (qp < 20 ? 0.55 : 0.68) * pow (2, (qp - SHIFT_QP) / 3.0);
 
-  snr_picture1 = picture1->distortion_y + picture1->distortion_u + picture1->distortion_v;
-  snr_picture2 = picture2->distortion_y + picture2->distortion_u + picture2->distortion_v;
-  bit_picture2 = picture2->bits_per_picture;
-  bit_picture1 = picture1->bits_per_picture;
-  
-  return rd_pic_decision(snr_picture1, snr_picture2, bit_picture1, bit_picture2, lambda_picture);
+  sse_picture1 = picture1->distortion.value[0] + picture1->distortion.value[1] + picture1->distortion.value[2];
+  sse_picture2 = picture2->distortion.value[0] + picture2->distortion.value[1] + picture2->distortion.value[2];
+ 
+  return rd_pic_decision(sse_picture1, sse_picture2, picture1->bits_per_picture, picture2->bits_per_picture, lambda_picture);
 }
 
diff --git a/lencod/src/refbuf.c b/lencod/src/refbuf.c
index 4502b9f..1932cd9 100644
--- a/lencod/src/refbuf.c
+++ b/lencod/src/refbuf.c
@@ -4,7 +4,7 @@
  * \file refbuf.c
  *
  * \brief
- *    Declarations of teh reference frame buffer types and functions
+ *    Declarations of the reference frame buffer types and functions
  ************************************************************************
  */
 
diff --git a/lencod/src/report.c b/lencod/src/report.c
new file mode 100644
index 0000000..67d56a9
--- /dev/null
+++ b/lencod/src/report.c
@@ -0,0 +1,1181 @@
+/*!
+ *  \file
+ *     report.c
+ *  \brief
+ *     Report related files()
+ *  \author
+ *   Main contributors (see contributors.h for copyright, address and affiliation details)
+ *   - Karsten Suehring                <suehring@hhi.de>
+ *   - Alexis Michael Tourapis         <alexismt@ieee.org>
+ ***********************************************************************
+ */
+
+#include "contributors.h"
+
+#include <time.h>
+#include <math.h>
+#include <sys/timeb.h>
+#include "global.h"
+
+#include "context_ini.h"
+#include "explicit_gop.h"
+#include "filehandle.h"
+#include "fmo.h"
+#include "image.h"
+#include "intrarefresh.h"
+#include "leaky_bucket.h"
+#include "me_epzs.h"
+#include "output.h"
+#include "parset.h"
+#include "report.h"
+
+
+StatParameters   statistics,  *stats = &statistics;
+DistortionParams distortions, *dist  = &distortions;
+static char DistortionType[3][20] = {"SAD", "SSE", "Hadamard SAD"};
+
+extern int frame_statistic_start;
+extern ColocatedParams *Co_located;
+extern ColocatedParams *Co_located_JV[MAX_PLANE];  //!< Co_located to be used during 4:4:4 independent mode encoding
+extern void Clear_Motion_Search_Module (void);
+void   report_log_mode(InputParameters *params, StatParameters *stats, int64 bit_use[NUM_SLICE_TYPES][2]);
+/*!
+ ************************************************************************
+ * \brief
+ *    Reports frame statistical data to a stats file
+ ************************************************************************
+ */
+void report_frame_statistic()
+{
+  FILE *p_stat_frm = NULL;
+  static int64 last_mode_use [NUM_SLICE_TYPES][MAXMODE];
+  static int64 last_mode_use_transform[NUM_SLICE_TYPES][MAXMODE][2];
+  static int   last_b8_mode_0[NUM_SLICE_TYPES][2];
+  static int   last_mode_chroma_use[4];
+  static int64 last_bit_ctr_n = 0;
+  int i;
+  char name[30];
+  int bitcounter;
+
+#ifndef WIN32
+  time_t now;
+  struct tm *l_time;
+  char string[1000];
+#else
+  char timebuf[128];
+#endif
+
+  // write to log file
+  if ((p_stat_frm = fopen("stat_frame.dat", "r")) == 0)            // check if file exists
+  {
+    if ((p_stat_frm = fopen("stat_frame.dat", "a")) == NULL)       // append new statistic at the end
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
+      error(errortext, 500);
+    }
+    else                                            // Create header for new log file
+    {
+      fprintf(p_stat_frm, " --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+      fprintf(p_stat_frm, "|            Encoder statistics. This file is generated during first encoding session, new sessions will be appended                                                                                                                                                                                                                                                                                                                                                              |\n");
+      fprintf(p_stat_frm, " --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+    }
+  }
+  else
+  {
+    fclose (p_stat_frm);
+    if ((p_stat_frm = fopen("stat_frame.dat", "a")) == NULL)       // File exists, just open for appending
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
+      error(errortext, 500);
+    }
+  }
+
+  if (frame_statistic_start)
+  {
+    fprintf(p_stat_frm, "|     ver     | Date  | Time  |    Sequence                  |Frm | QP |P/MbInt|   Bits   |  SNRY  |  SNRU  |  SNRV  |  I4  |  I8  | I16  | IC0  | IC1  | IC2  | IC3  | PI4  | PI8  | PI16 |  P0  |  P1  |  P2  |  P3  | P1*4*| P1*8*| P2*4*| P2*8*| P3*4*| P3*8*|  P8  | P8:4 | P4*4*| P4*8*| P8:5 | P8:6 | P8:7 | BI4  | BI8  | BI16 |  B0  |  B1  |  B2  |  B3  | B0*4*| B0*8*| B1*4*| B1*8*| B2*4*| B2*8*| B3*4*| B3*8*|  B8  | B8:0 |B80*4*|B80*8*| B8:4 | B4*4*| B4*8*| B8:5 | B8:6 | B8:7 |\n");
+    fprintf(p_stat_frm, " ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
+  }
+
+  //report
+  fprintf(p_stat_frm, "|%4s/%s", VERSION, EXT_VERSION);
+
+#ifdef WIN32
+  _strdate( timebuf );
+  fprintf(p_stat_frm, "| %1.5s |", timebuf);
+
+  _strtime( timebuf);
+  fprintf(p_stat_frm, " % 1.5s |", timebuf);
+#else
+  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
+  time (&now);
+  l_time = localtime (&now);
+  strftime (string, sizeof string, "%d-%b-%Y", l_time);
+  fprintf(p_stat_frm, "| %1.5s |", string );
+
+  strftime (string, sizeof string, "%H:%M:%S", l_time);
+  fprintf(p_stat_frm, " %1.5s |", string);
+#endif
+
+  for (i=0;i<30;i++)
+    name[i]=params->infile[i + imax(0,(int) (strlen(params->infile)- 30))]; // write last part of path, max 30 chars
+
+  fprintf(p_stat_frm, "%30.30s|", name);
+  fprintf(p_stat_frm, "%3d |", frame_no);
+  fprintf(p_stat_frm, "%3d |", img->qp);
+  fprintf(p_stat_frm, "  %d/%d  |", params->PicInterlace, params->MbInterlace);
+
+
+  if (img->frm_number == 0 && img->frame_num == 0)
+  {
+    bitcounter = (int) stats->bit_counter[I_SLICE];
+  }
+  else
+  {
+    bitcounter = (int) (stats->bit_ctr_n - last_bit_ctr_n);
+    last_bit_ctr_n = stats->bit_ctr_n;
+  }
+
+  //report bitrate
+  fprintf(p_stat_frm, " %9d|", bitcounter);
+
+  //report snr's  
+  fprintf(p_stat_frm, " %2.4f| %2.4f| %2.4f|", dist->metric[PSNR].value[0], dist->metric[PSNR].value[1], dist->metric[PSNR].value[2]);
+
+  //report modes
+  //I-Modes
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I4MB ] - last_mode_use[I_SLICE][I4MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I8MB ] - last_mode_use[I_SLICE][I8MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I16MB] - last_mode_use[I_SLICE][I16MB]);
+
+  //chroma intra mode
+  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[0] - last_mode_chroma_use[0]);
+  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[1] - last_mode_chroma_use[1]);
+  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[2] - last_mode_chroma_use[2]);
+  fprintf(p_stat_frm, " %5d|", stats->intra_chroma_mode[3] - last_mode_chroma_use[3]);
+
+  //P-Modes
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I4MB ] - last_mode_use[P_SLICE][I4MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I8MB ] - last_mode_use[P_SLICE][I8MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I16MB] - last_mode_use[P_SLICE][I16MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][0    ] - last_mode_use[P_SLICE][0   ]);
+
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][1    ] - last_mode_use[P_SLICE][1   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][2    ] - last_mode_use[P_SLICE][2   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][3    ] - last_mode_use[P_SLICE][3   ]);
+  
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][1][0] - last_mode_use_transform[P_SLICE][1][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][1][1] - last_mode_use_transform[P_SLICE][1][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][2][0] - last_mode_use_transform[P_SLICE][2][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][2][1] - last_mode_use_transform[P_SLICE][2][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][3][0] - last_mode_use_transform[P_SLICE][3][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][3][1] - last_mode_use_transform[P_SLICE][3][1]);
+
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][P8x8 ] - last_mode_use[P_SLICE][P8x8]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][4    ] - last_mode_use[P_SLICE][4   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][4][0] - last_mode_use_transform[P_SLICE][4][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][4][1] - last_mode_use_transform[P_SLICE][4][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][5    ] - last_mode_use[P_SLICE][5   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][6    ] - last_mode_use[P_SLICE][6   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][7    ] - last_mode_use[P_SLICE][7   ]);
+
+  //B-Modes
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I4MB ] - last_mode_use[B_SLICE][I4MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I8MB ] - last_mode_use[B_SLICE][I8MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I16MB] - last_mode_use[B_SLICE][I16MB]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][0    ] - last_mode_use[B_SLICE][0   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][1    ] - last_mode_use[B_SLICE][1   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][2    ] - last_mode_use[B_SLICE][2   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][3    ] - last_mode_use[B_SLICE][3   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][0][0] - last_mode_use_transform[B_SLICE][0][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][0][1] - last_mode_use_transform[B_SLICE][0][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][1][0] - last_mode_use_transform[B_SLICE][1][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][1][1] - last_mode_use_transform[B_SLICE][1][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][2][0] - last_mode_use_transform[B_SLICE][2][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][2][1] - last_mode_use_transform[B_SLICE][2][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][3][0] - last_mode_use_transform[B_SLICE][3][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][3][1] - last_mode_use_transform[B_SLICE][3][1]);
+
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][P8x8] - last_mode_use[B_SLICE][P8x8]);
+  fprintf(p_stat_frm, " %d|", (stats->b8_mode_0_use [B_SLICE][0]+stats->b8_mode_0_use [B_SLICE][1]) - (last_b8_mode_0[B_SLICE][0]+last_b8_mode_0[B_SLICE][1]));
+  fprintf(p_stat_frm, " %5d|", stats->b8_mode_0_use [B_SLICE][0] - last_b8_mode_0[B_SLICE][0]);
+  fprintf(p_stat_frm, " %5d|", stats->b8_mode_0_use [B_SLICE][1] - last_b8_mode_0[B_SLICE][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][4   ] - last_mode_use[B_SLICE][4   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][4][0] - last_mode_use_transform[B_SLICE][4][0]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][4][1] - last_mode_use_transform[B_SLICE][4][1]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][5   ] - last_mode_use[B_SLICE][5   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][6   ] - last_mode_use[B_SLICE][6   ]);
+  fprintf(p_stat_frm, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][7   ] - last_mode_use[B_SLICE][7   ]);
+
+  fprintf(p_stat_frm, "\n");
+
+  //save the last results
+  memcpy(last_mode_use[I_SLICE], stats->mode_use[I_SLICE], MAXMODE *  sizeof(int64));
+  memcpy(last_mode_use[P_SLICE], stats->mode_use[P_SLICE], MAXMODE *  sizeof(int64));
+  memcpy(last_mode_use[B_SLICE], stats->mode_use[B_SLICE], MAXMODE *  sizeof(int64));
+  memcpy(last_mode_use_transform[P_SLICE], stats->mode_use_transform[P_SLICE], 2 * MAXMODE * sizeof(int64));
+  memcpy(last_mode_use_transform[B_SLICE], stats->mode_use_transform[B_SLICE], 2 * MAXMODE * sizeof(int64));
+  memcpy(last_b8_mode_0[B_SLICE], stats->b8_mode_0_use[B_SLICE], 2 *  sizeof(int));
+  memcpy(last_mode_chroma_use, stats->intra_chroma_mode, 4 *  sizeof(int));
+
+  frame_statistic_start = 0;
+  fclose(p_stat_frm);
+}
+
+
+double report_slice_pred_stats(FILE *p_stat, StatParameters *stats, int slice_type, double bit_use, char *slice_name)
+{
+  fprintf(p_stat,"\n ---------------------|----------------|-----------------|");
+  fprintf(p_stat,"\n   %8s           |   Mode used    | MotionInfo bits |", slice_name);
+  fprintf(p_stat,"\n ---------------------|----------------|-----------------|");
+  fprintf(p_stat,"\n Mode  0  (copy)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[slice_type][0   ], (double)stats->bit_use_mode[slice_type][0   ] / bit_use);
+  fprintf(p_stat,"\n Mode  1  (16x16)     |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[slice_type][1   ], (double)stats->bit_use_mode[slice_type][1   ] / bit_use);
+  fprintf(p_stat,"\n Mode  2  (16x8)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[slice_type][2   ], (double)stats->bit_use_mode[slice_type][2   ] / bit_use);
+  fprintf(p_stat,"\n Mode  3  (8x16)      |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[slice_type][3   ], (double)stats->bit_use_mode[slice_type][3   ] / bit_use);
+  fprintf(p_stat,"\n Mode  4  (8x8)       |  %5" FORMAT_OFF_T  "         |    %8.2f     |", stats->mode_use[slice_type][P8x8], (double)stats->bit_use_mode[slice_type][P8x8] / bit_use);
+  fprintf(p_stat,"\n Mode  5  intra 4x4   |  %5" FORMAT_OFF_T  "         |-----------------|", stats->mode_use[slice_type][I4MB]);
+  fprintf(p_stat,"\n Mode  6  intra 8x8   |  %5" FORMAT_OFF_T  "         |", stats->mode_use[slice_type][I8MB]);
+  fprintf(p_stat,"\n Mode  7+ intra 16x16 |  %5" FORMAT_OFF_T  "         |", stats->mode_use[slice_type][I16MB]);
+  fprintf(p_stat,"\n Mode     intra IPCM  |  %5" FORMAT_OFF_T  "         |", stats->mode_use[slice_type][IPCM ]);
+
+  return (double)(stats->bit_use_mode[slice_type][0] + stats->bit_use_mode[slice_type][1] + stats->bit_use_mode[slice_type][2]
+  + stats->bit_use_mode[slice_type][3] + stats->bit_use_mode[slice_type][P8x8]) / bit_use;
+}
+
+/*!
+ ***********************************************************************
+ * \brief
+ *    Terminates and reports statistics on error.
+ *
+ ***********************************************************************
+ */
+void report_stats_on_error(void)
+{
+  params->no_frames = img->frm_number;
+  free_encoder_memory(img);
+  exit (-1);
+}
+
+
+void report_stats(InputParameters *params, StatParameters *stats, int64 bit_use[NUM_SLICE_TYPES][2], float frame_rate)
+{
+  FILE *p_stat;                    //!< status file for the last encoding session
+  double mean_motion_info_bit_use[NUM_SLICE_TYPES] = {0.0};
+  int i;
+
+  if (strlen(params->StatsFile) == 0)
+    strcpy (params->StatsFile,"stats.dat");
+
+  if ((p_stat = fopen(params->StatsFile, "wt")) == 0)
+  {
+    snprintf(errortext, ET_SIZE, "Error open file %s", params->StatsFile);
+    error(errortext, 500);
+  }
+
+  fprintf(p_stat," -------------------------------------------------------------- \n");
+  fprintf(p_stat,"  This file contains statistics for the last encoded sequence   \n");
+  fprintf(p_stat," -------------------------------------------------------------- \n");
+  fprintf(p_stat,   " Sequence                     : %s\n", params->infile);
+  fprintf(p_stat,   " No.of coded pictures         : %4d\n", stats->frame_counter);
+  fprintf(p_stat,   " Freq. for encoded bitstream  : %4.0f\n", frame_rate);
+
+  fprintf(p_stat,   " I Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_st[I_SLICE] / 1000);
+  fprintf(p_stat,   " P Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_st[P_SLICE] / 1000);
+  fprintf(p_stat,   " B Slice Bitrate(kb/s)        : %6.2f\n", stats->bitrate_st[B_SLICE] / 1000);
+  fprintf(p_stat,   " Total Bitrate(kb/s)          : %6.2f\n", stats->bitrate / 1000);
+
+  for (i = 0; i < 3; i++)
+  {
+    fprintf(p_stat," ME Level %1d Metric            : %s\n", i, DistortionType[params->MEErrorMetric[i]]);
+  }
+  fprintf(p_stat," Mode Decision Metric         : %s\n", DistortionType[params->ModeDecisionMetric]);
+
+  switch ( params->ChromaMEEnable )
+  {
+  case 1:
+    fprintf(p_stat," ME for components            : YCbCr\n");
+    break;
+  default:
+    fprintf(p_stat," ME for components            : Y\n");
+    break;
+  }
+
+  fprintf(p_stat,  " Image format                 : %dx%d\n", params->output.width, params->output.height);
+
+  if (params->intra_upd)
+    fprintf(p_stat," Error robustness             : On\n");
+  else
+    fprintf(p_stat," Error robustness             : Off\n");
+
+  fprintf(p_stat,  " Search range                 : %d\n", params->search_range);
+
+  fprintf(p_stat,   " Total number of references   : %d\n", params->num_ref_frames);
+  fprintf(p_stat,   " References for P slices      : %d\n", params->P_List0_refs ? params->P_List0_refs : params->num_ref_frames);
+
+  if (stats->frame_ctr[B_SLICE]!=0)
+  {
+    fprintf(p_stat, " List0 refs for B slices      : %d\n", params->B_List0_refs ? params->B_List0_refs : params->num_ref_frames);
+    fprintf(p_stat, " List1 refs for B slices      : %d\n", params->B_List1_refs ? params->B_List1_refs : params->num_ref_frames);
+  }
+
+  fprintf(p_stat,   " Profile/Level IDC            : (%d,%d)\n", params->ProfileIDC, params->LevelIDC);
+  if (params->symbol_mode == CAVLC)
+    fprintf(p_stat,   " Entropy coding method        : CAVLC\n");
+  else
+    fprintf(p_stat,   " Entropy coding method        : CABAC\n");
+
+  if (params->MbInterlace)
+    fprintf(p_stat, " MB Field Coding : On \n");
+
+  if (params->SearchMode == EPZS)
+    EPZSOutputStats(params, p_stat, 1);
+
+  if (params->full_search == 2)
+    fprintf(p_stat," Search range restrictions    : none\n");
+  else if (params->full_search == 1)
+    fprintf(p_stat," Search range restrictions    : older reference frames\n");
+  else
+    fprintf(p_stat," Search range restrictions    : smaller blocks and older reference frames\n");
+
+  if (params->rdopt)
+    fprintf(p_stat," RD-optimized mode decision   : used\n");
+  else
+    fprintf(p_stat," RD-optimized mode decision   : not used\n");
+
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|");
+  fprintf(p_stat,"\n     Item             |     Intra      |   All frames  |");
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|");
+  fprintf(p_stat,"\n SNR Y(dB)            |");
+  fprintf(p_stat," %5.2f          |", dist->metric[PSNR].avslice[I_SLICE][0]);
+  fprintf(p_stat," %5.2f         |", dist->metric[PSNR].average[0]);
+  fprintf(p_stat,"\n SNR U/V (dB)         |");
+  fprintf(p_stat," %5.2f/%5.2f    |", dist->metric[PSNR].avslice[I_SLICE][1], dist->metric[PSNR].avslice[I_SLICE][2]);
+  fprintf(p_stat," %5.2f/%5.2f   |", dist->metric[PSNR].average[1], dist->metric[PSNR].average[2]);
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|");
+  fprintf(p_stat,"\n");
+
+  // QUANT.
+  fprintf(p_stat,"\n Average quant        |");
+  fprintf(p_stat," %5d          |", iabs(params->qp0));
+  fprintf(p_stat," %5.2f         |", (float)stats->quant1/dmax(1.0,(float)stats->quant0));
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|---------------|");
+  fprintf(p_stat,"\n     SNR              |        I       |       P       |       B       |");
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|---------------|");
+  fprintf(p_stat,"\n SNR Y(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |",
+    dist->metric[PSNR].avslice[I_SLICE][0], dist->metric[PSNR].avslice[P_SLICE][0], dist->metric[PSNR].avslice[B_SLICE][0]);
+  fprintf(p_stat,"\n SNR U(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |",
+    dist->metric[PSNR].avslice[I_SLICE][1], dist->metric[PSNR].avslice[P_SLICE][1], dist->metric[PSNR].avslice[B_SLICE][1]);
+  fprintf(p_stat,"\n SNR V(dB)            |      %5.3f    |     %5.3f    |     %5.3f    |",
+    dist->metric[PSNR].avslice[I_SLICE][2], dist->metric[PSNR].avslice[P_SLICE][2], dist->metric[PSNR].avslice[B_SLICE][2]);
+  fprintf(p_stat,"\n ---------------------|----------------|---------------|---------------|");  
+  fprintf(p_stat,"\n");
+
+  // MODE
+  fprintf(p_stat,"\n ---------------------|----------------|");
+  fprintf(p_stat,"\n   Intra              |   Mode used    |");
+  fprintf(p_stat,"\n ---------------------|----------------|");
+  fprintf(p_stat,"\n Mode 0  intra 4x4    |  %5" FORMAT_OFF_T  "         |", stats->mode_use[I_SLICE][I4MB ]);
+  fprintf(p_stat,"\n Mode 1  intra 8x8    |  %5" FORMAT_OFF_T  "         |", stats->mode_use[I_SLICE][I8MB ]);
+  fprintf(p_stat,"\n Mode 2+ intra 16x16  |  %5" FORMAT_OFF_T  "         |", stats->mode_use[I_SLICE][I16MB]);
+  fprintf(p_stat,"\n Mode    intra IPCM   |  %5" FORMAT_OFF_T  "         |", stats->mode_use[I_SLICE][IPCM ]);
+
+  // P slices
+  if (stats->frame_ctr[P_SLICE]!=0)
+  {    
+    mean_motion_info_bit_use[P_SLICE] = report_slice_pred_stats(p_stat, stats, P_SLICE,(double) bit_use[P_SLICE][0], "P Slice ");
+  }
+  // B slices
+  if (stats->frame_ctr[B_SLICE]!=0)
+  {
+    mean_motion_info_bit_use[B_SLICE] = report_slice_pred_stats(p_stat, stats, B_SLICE,(double) bit_use[B_SLICE][0], "B Slice ");
+  }
+  // SP slices
+  if (stats->frame_ctr[SP_SLICE]!=0)
+  {    
+    mean_motion_info_bit_use[SP_SLICE] = report_slice_pred_stats(p_stat, stats, SP_SLICE,(double) bit_use[SP_SLICE][0], "SP Slice");
+  }
+
+
+  fprintf(p_stat,"\n ---------------------|----------------|");
+  fprintf(p_stat,"\n");
+
+  fprintf(p_stat,"\n ---------------------|----------------|----------------|----------------|");
+  fprintf(p_stat,"\n  Bit usage:          |      Intra     |      Inter     |    B frame     |");
+  fprintf(p_stat,"\n ---------------------|----------------|----------------|----------------|");
+
+  fprintf(p_stat,"\n Header               |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[P_SLICE] / bit_use[P_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_header[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Mode                 |");
+  fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[P_SLICE] / bit_use[P_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float)stats->bit_use_mb_type[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Motion Info          |");
+  fprintf(p_stat,"        ./.     |");
+  fprintf(p_stat," %10.2f     |", mean_motion_info_bit_use[P_SLICE]);
+  fprintf(p_stat," %10.2f     |", mean_motion_info_bit_use[B_SLICE]);
+
+  fprintf(p_stat,"\n CBP Y/C              |");
+  fprintf(p_stat," %10.2f     |", (float) stats->tmp_bit_use_cbp[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->tmp_bit_use_cbp[P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->tmp_bit_use_cbp[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Coeffs. Y            |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[0][I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[0][P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[0][B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Coeffs. C            |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeffC[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeffC[P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeffC[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Coeffs. CB           |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[1][I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[1][P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[1][B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Coeffs. CB           |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[2][I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[2][P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_coeff[2][B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Delta quant          |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_delta_quant[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_delta_quant[P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_delta_quant[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n Stuffing Bits        |");
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_stuffingBits[I_SLICE] / bit_use[I_SLICE][0]);
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_stuffingBits[P_SLICE] / bit_use[P_SLICE][0]);   
+  fprintf(p_stat," %10.2f     |", (float) stats->bit_use_stuffingBits[B_SLICE] / bit_use[B_SLICE][0]);
+
+  fprintf(p_stat,"\n ---------------------|----------------|----------------|----------------|");
+  fprintf(p_stat,"\n average bits/frame   |");
+  fprintf(p_stat," %10.2f     |", (float) bit_use[I_SLICE][1] / (float) bit_use[I_SLICE][0] );
+  fprintf(p_stat," %10.2f     |", (float) bit_use[P_SLICE][1] / (float) bit_use[P_SLICE][0] );
+  fprintf(p_stat," %10.2f     |", (float) bit_use[B_SLICE][1] / (float) bit_use[B_SLICE][0] );
+  fprintf(p_stat,"\n ---------------------|----------------|----------------|----------------|");
+  fprintf(p_stat,"\n");
+
+  fclose(p_stat);
+}
+
+
+void report_log(InputParameters *params, StatParameters *stats, float frame_rate)
+{
+  char name[40];
+  int i;
+#ifndef WIN32
+  time_t now;
+  struct tm *l_time;
+  char string[1000];
+#else
+  char timebuf[128];
+#endif
+
+  if ((p_log = fopen("log.dat", "r")) == 0)         // check if file exists
+  {
+    if ((p_log = fopen("log.dat", "a")) == NULL)    // append new statistic at the end
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log.dat");
+      error(errortext, 500);
+    }
+    else                                            // Create header for new log file
+    {
+      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
+      fprintf(p_log,"|                          Encoder statistics. This file is generated during first encoding session, new sessions will be appended                                                                                                                                                                                 |\n");
+      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
+      fprintf(p_log,"|     ver     | Date  | Time  |               Sequence                 | #Img |P/MbInt| QPI| QPP| QPB| Format  |Iperiod| #B | FMES | Hdmd | S.R |#Ref | Freq |Coding|RD-opt|Intra upd|8x8Tr| SNRY 1| SNRU 1| SNRV 1| SNRY N| SNRU N| SNRV N|#Bitr I|#Bitr P|#Bitr B|#Bitr IPB|     Total Time   |      Me Time     |\n");
+      fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
+
+    }
+  }
+  else
+  {
+    fclose (p_log);
+    if ((p_log = fopen("log.dat", "a")) == NULL)         // File exists, just open for appending
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log.dat");
+      error(errortext, 500);
+    }
+  }
+  fprintf(p_log,"|%5s/%-5s", VERSION, EXT_VERSION);
+
+#ifdef WIN32
+  _strdate( timebuf );
+  fprintf(p_log,"| %1.5s |", timebuf );
+
+  _strtime( timebuf);
+  fprintf(p_log," % 1.5s |", timebuf);
+#else
+  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
+  time (&now);
+  l_time = localtime (&now);
+  strftime (string, sizeof string, "%d-%b-%Y", l_time);
+  fprintf(p_log,"| %1.5s |", string );
+
+  strftime (string, sizeof string, "%H:%M:%S", l_time);
+  fprintf(p_log," %1.5s |", string );
+#endif
+
+  for (i=0; i < 40; i++)
+    name[i] = params->infile[i + imax(0, ((int) strlen(params->infile)) - 40)]; // write last part of path, max 40 chars
+  fprintf(p_log,"%40.40s|",name);
+
+  fprintf(p_log,"%5d |  %d/%d  |", params->no_frames, params->PicInterlace, params->MbInterlace);
+  fprintf(p_log," %-3d| %-3d| %-3d|", params->qp0, params->qpN, params->qpB);
+
+  fprintf(p_log,"%4dx%-4d|", params->output.width, params->output.height);
+  fprintf(p_log,"  %3d  |%3d |", params->intra_period, stats->successive_Bframe);
+
+
+  switch( params->SearchMode ) 
+  {
+  case UM_HEX:
+    fprintf(p_log,"  HEX |");
+    break;
+  case UM_HEX_SIMPLE:
+    fprintf(p_log," SHEX |");
+    break;
+  case EPZS:
+    fprintf(p_log," EPZS |");
+    break;
+  case FAST_FULL_SEARCH:
+    fprintf(p_log,"  FFS |");
+    break;
+  default:
+    fprintf(p_log,"  FS  |");
+    break;
+  }
+
+  fprintf(p_log,"  %1d%1d%1d |", params->MEErrorMetric[F_PEL], params->MEErrorMetric[H_PEL], params->MEErrorMetric[Q_PEL]);
+
+  fprintf(p_log," %3d | %2d  |", params->search_range, params->num_ref_frames );
+
+  fprintf(p_log," %5.2f|", (img->framerate *(float) (stats->successive_Bframe + 1)) / (float)(params->jumpd + 1));
+
+  if (params->symbol_mode == CAVLC)
+    fprintf(p_log," CAVLC|");
+  else
+    fprintf(p_log," CABAC|");
+
+  fprintf(p_log,"   %d  |", params->rdopt);
+
+  if (params->intra_upd == 1)
+    fprintf(p_log,"   ON    |");
+  else
+    fprintf(p_log,"   OFF   |");
+
+  fprintf(p_log,"  %d  |", params->Transform8x8Mode);
+
+  fprintf(p_log,"%7.3f|%7.3f|%7.3f|", 
+    dist->metric[PSNR].avslice[I_SLICE][0],
+    dist->metric[PSNR].avslice[I_SLICE][1],
+    dist->metric[PSNR].avslice[I_SLICE][2]);
+  fprintf(p_log,"%7.3f|%7.3f|%7.3f|", dist->metric[PSNR].average[0],dist->metric[PSNR].average[1],dist->metric[PSNR].average[2]);
+  /*
+  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", dist->metric[PSNR].avslice[I_SLICE][0], dist->metric[PSNR].avslice[I_SLICE][1], dist->metric[PSNR].avslice[I_SLICE][2]);
+  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", dist->metric[PSNR].avslice[P_SLICE][0], dist->metric[PSNR].avslice[P_SLICE][1], dist->metric[PSNR].avslice[P_SLICE][2]);
+  fprintf(p_log,"%-5.3f|%-5.3f|%-5.3f|", dist->metric[PSNR].avslice[B_SLICE][0], dist->metric[PSNR].avslice[B_SLICE][1], dist->metric[PSNR].avslice[B_SLICE][2]);
+  */
+  fprintf(p_log,"%7.0f|%7.0f|%7.0f|%9.0f|", stats->bitrate_st[I_SLICE],stats->bitrate_st[P_SLICE],stats->bitrate_st[B_SLICE], stats->bitrate);
+
+  fprintf(p_log,"   %12d   |   %12d   |", (int)tot_time,(int)me_tot_time);
+
+
+  fprintf(p_log,"\n");
+
+  fclose(p_log);
+
+  p_log = fopen("data.txt", "a");
+
+  if ((stats->successive_Bframe != 0) && (stats->frame_ctr[B_SLICE] != 0)) // B picture used
+  {
+    fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " "
+      "%2.2f %2.2f %2.2f %5d "
+      "%2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " %5" FORMAT_OFF_T  " %.3f\n",
+      params->no_frames, params->qp0, params->qpN,
+      dist->metric[PSNR].avslice[I_SLICE][0],
+      dist->metric[PSNR].avslice[I_SLICE][1],
+      dist->metric[PSNR].avslice[I_SLICE][2],
+      stats->bit_counter[I_SLICE],
+      0.0,
+      0.0,
+      0.0,
+      0,
+      dist->metric[PSNR].average[0],
+      dist->metric[PSNR].average[1],
+      dist->metric[PSNR].average[2],
+      (stats->bit_counter[I_SLICE] + stats->bit_ctr) / stats->frame_counter,
+      stats->bit_counter[B_SLICE] / stats->frame_ctr[B_SLICE],
+      (double) 0.001 * tot_time / (stats->frame_counter));
+  }
+  else
+  {
+    if (params->no_frames != 0)
+      fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " "
+      "%2.2f %2.2f %2.2f %5d "
+      "%2.2f %2.2f %2.2f %5" FORMAT_OFF_T  " %5d %.3f\n",
+      params->no_frames, params->qp0, params->qpN,
+      dist->metric[PSNR].avslice[I_SLICE][0],
+      dist->metric[PSNR].avslice[I_SLICE][1],
+      dist->metric[PSNR].avslice[I_SLICE][2],
+      stats->bit_counter[I_SLICE],
+      0.0,
+      0.0,
+      0.0,
+      0,
+      dist->metric[PSNR].average[0],
+      dist->metric[PSNR].average[1],
+      dist->metric[PSNR].average[2],
+      (stats->bit_counter[I_SLICE] + stats->bit_ctr)/ stats->frame_counter,
+      0,
+      (double)0.001*tot_time/params->no_frames);
+  }
+
+  fclose(p_log);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Reports the gathered information to appropriate outputs
+ * \par Input:
+ *    struct inp_par *inp,                                            \n
+ *    ImageParameters *img,                                            \n
+ *    struct stat_par *stats,                                          \n
+ *
+ * \par Output:
+ *    None
+ ************************************************************************
+ */
+void report( ImageParameters *img, InputParameters *params, StatParameters *stats)
+{
+  int64 bit_use[NUM_SLICE_TYPES][2];
+  int i,j;
+  int64 total_bits;
+  float frame_rate;
+
+  bit_use[ I_SLICE][0] = stats->frame_ctr[I_SLICE];
+  bit_use[ P_SLICE][0] = imax(stats->frame_ctr[P_SLICE ] + stats->frame_ctr[SP_SLICE], 1);
+  bit_use[ B_SLICE][0] = imax(stats->frame_ctr[B_SLICE ], 1);
+  bit_use[SP_SLICE][0] = imax(stats->frame_ctr[SP_SLICE], 1);
+
+  //  Accumulate bit usage for inter and intra frames
+  for (j=0; j < NUM_SLICE_TYPES; j++)
+  {
+    bit_use[j][1] = 0;
+  }
+
+  for (j=0; j < NUM_SLICE_TYPES; j++)
+  {
+    for(i=0; i < MAXMODE; i++)
+      bit_use[j][1] += stats->bit_use_mode[j][i];
+
+    bit_use[j][1] += stats->bit_use_header[j];
+    bit_use[j][1] += stats->bit_use_mb_type[j];
+    bit_use[j][1] += stats->tmp_bit_use_cbp[j];
+    bit_use[j][1] += stats->bit_use_coeffC[j];
+    bit_use[j][1] += stats->bit_use_coeff[0][j];   
+    bit_use[j][1] += stats->bit_use_coeff[1][j]; 
+    bit_use[j][1] += stats->bit_use_coeff[2][j]; 
+    bit_use[j][1] += stats->bit_use_delta_quant[j];
+    bit_use[j][1] += stats->bit_use_stuffingBits[j];
+  }
+
+  frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (params->jumpd + 1);
+
+  //! Currently adding NVB bits on P rate. Maybe additional stats info should be created instead and added in log file  
+  stats->bitrate_st[ I_SLICE] = (stats->bit_counter[ I_SLICE]) * (frame_rate) / (float) (stats->frame_counter);
+  stats->bitrate_st[ P_SLICE] = (stats->bit_counter[ P_SLICE]) * (frame_rate) / (float) (stats->frame_counter);
+  stats->bitrate_st[ B_SLICE] = (stats->bit_counter[ B_SLICE]) * (frame_rate) / (float) (stats->frame_counter);
+  stats->bitrate_st[SP_SLICE] = (stats->bit_counter[SP_SLICE]) * (frame_rate) / (float) (stats->frame_counter);
+
+  switch (params->Verbose)
+  {
+  case 0:
+  case 1:
+  default:
+    fprintf(stdout,"------------------ Average data all frames  -----------------------------------\n\n");
+    break;
+  case 2:
+    fprintf(stdout,"------------------------------------  Average data all frames  ---------------------------------\n\n");
+    break;
+  }
+
+  if (params->Verbose != 0)
+  {
+    DistMetric *snr     = &dist->metric[PSNR    ];
+    DistMetric *sse     = &dist->metric[SSE     ];
+    DistMetric *snr_rgb = &dist->metric[PSNR_RGB];
+    DistMetric *sse_rgb = &dist->metric[SSE_RGB ];
+
+    int  impix    = params->output.size_cmp[0];
+    int  impix_cr = params->output.size_cmp[1];
+
+    float csnr_y = psnr(img->max_imgpel_value_comp_sq[0], impix   , sse->average[0]);
+    float csnr_u = psnr(img->max_imgpel_value_comp_sq[1], impix_cr, sse->average[1]);
+    float csnr_v = psnr(img->max_imgpel_value_comp_sq[2], impix_cr, sse->average[2]);
+
+    fprintf(stdout,  " Total encoding time for the seq.  : %.3f sec (%.2f fps)\n", tot_time*0.001, 1000.0 * (stats->frame_counter) / tot_time);
+    fprintf(stdout,  " Total ME time for sequence        : %.3f sec \n\n", me_tot_time*0.001);
+
+    fprintf(stdout," Y { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n", 
+      snr->average[0], csnr_y, sse->average[0]/impix);
+    fprintf(stdout," U { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n",
+      snr->average[1], csnr_u, sse->average[1]/impix_cr);
+    fprintf(stdout," V { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n",
+      snr->average[2], csnr_v, sse->average[2]/impix_cr);
+
+    if(params->DistortionYUVtoRGB == 1)
+    {
+      float csnr_r = psnr(img->max_imgpel_value_comp_sq[0], impix, sse_rgb->average[0]);
+      float csnr_g = psnr(img->max_imgpel_value_comp_sq[1], impix, sse_rgb->average[1]);
+      float csnr_b = psnr(img->max_imgpel_value_comp_sq[2], impix, sse_rgb->average[2]);
+
+      fprintf(stdout," R { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n", 
+        snr_rgb->average[0], csnr_r, sse_rgb->average[0]/impix);
+      fprintf(stdout," G { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n",
+        snr_rgb->average[1], csnr_g, sse_rgb->average[1]/impix);
+      fprintf(stdout," B { PSNR (dB), cSNR (dB), MSE }   : { %5.2f, %5.2f, %5.2f }\n",
+        snr_rgb->average[2], csnr_b, sse_rgb->average[2]/impix);
+    }
+
+    if (params->Distortion[SSIM] == 1)
+    {
+      if(params->DistortionYUVtoRGB == 1)
+      {
+        fprintf(stdout," SSIM {Y, R}                       : { %5.4f, %5.4f }\n", dist->metric[SSIM].average[0], dist->metric[SSIM_RGB].average[0]);
+        fprintf(stdout," SSIM {U, G}                       : { %5.4f, %5.4f }\n", dist->metric[SSIM].average[1], dist->metric[SSIM_RGB].average[1]);
+        fprintf(stdout," SSIM {V, B}                       : { %5.4f, %5.4f }\n", dist->metric[SSIM].average[2], dist->metric[SSIM_RGB].average[2]);
+      }
+      else
+      {
+        fprintf(stdout," Y SSIM                            : %5.4f\n", dist->metric[SSIM].average[0]);
+        fprintf(stdout," U SSIM                            : %5.4f\n", dist->metric[SSIM].average[1]);
+        fprintf(stdout," V SSIM                            : %5.4f\n", dist->metric[SSIM].average[2]);
+      }
+    }
+    if (params->Distortion[MS_SSIM] == 1)
+    {
+      if(params->DistortionYUVtoRGB == 1)
+      {
+        fprintf(stdout," MS-SSIM {Y, R}                    : { %5.4f, %5.4f }\n", dist->metric[MS_SSIM].average[0], dist->metric[MS_SSIM_RGB].average[0]);
+        fprintf(stdout," MS-SSIM {U, G}                    : { %5.4f, %5.4f }\n", dist->metric[MS_SSIM].average[1], dist->metric[MS_SSIM_RGB].average[1]);
+        fprintf(stdout," MS-SSIM {V, B}                    : { %5.4f, %5.4f }\n", dist->metric[MS_SSIM].average[2], dist->metric[MS_SSIM_RGB].average[2]);
+      }
+      else
+      {
+        fprintf(stdout," Y MS-SSIM                         : %5.4f\n", dist->metric[MS_SSIM].average[0]);
+        fprintf(stdout," U MS-SSIM                         : %5.4f\n", dist->metric[MS_SSIM].average[1]);
+        fprintf(stdout," V MS-SSIM                         : %5.4f\n", dist->metric[MS_SSIM].average[2]);
+      }
+    }
+    fprintf(stdout,"\n");
+  }
+  else
+    fprintf(stdout,  " Total encoding time for the seq.  : %.3f sec (%.2f fps)\n\n", tot_time*0.001, 1000.0 * (stats->frame_counter) / tot_time);
+
+  total_bits = stats->bit_ctr_parametersets;
+  for (i = 0; i < NUM_SLICE_TYPES; i++)
+    total_bits += stats->bit_counter[i];
+
+  if (stats->frame_ctr[B_SLICE] != 0)
+  {
+    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", B %" FORMAT_OFF_T  " NVB %d) \n",
+      total_bits,  stats->bit_counter[I_SLICE], stats->bit_counter[P_SLICE], stats->bit_counter[B_SLICE], stats->bit_ctr_parametersets);
+  }
+  else if (params->sp_periodicity == 0)
+  {
+    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", NVB %d) \n",
+      total_bits, stats->bit_counter[I_SLICE], stats->bit_counter[P_SLICE], stats->bit_ctr_parametersets);
+  }
+  else
+  {
+    fprintf(stdout, " Total bits                        : %" FORMAT_OFF_T  " (I %" FORMAT_OFF_T  ", P %" FORMAT_OFF_T  ", NVB %d) \n",
+      total_bits, stats->bit_counter[I_SLICE], stats->bit_counter[P_SLICE], stats->bit_ctr_parametersets);
+  }
+
+  frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (params->jumpd + 1);
+
+  stats->bitrate= ((float) total_bits * frame_rate) / ((float) (stats->frame_counter));
+  fprintf(stdout, " Bit rate (kbit/s)  @ %2.2f Hz     : %5.2f\n", frame_rate, stats->bitrate / 1000);
+
+  fprintf(stdout, " Bits to avoid Startcode Emulation : %d \n", stats->bit_ctr_emulationprevention);
+  fprintf(stdout, " Bits for parameter sets           : %d \n\n", stats->bit_ctr_parametersets);
+
+  switch (params->Verbose)
+  {
+  case 0:
+  case 1:
+  default:
+    fprintf(stdout,"-------------------------------------------------------------------------------\n");
+    break;
+  case 2:
+    fprintf(stdout,"------------------------------------------------------------------------------------------------\n");
+    break;
+  }  
+  fprintf(stdout,"Exit JM %s encoder ver %s ", JM, VERSION);
+  fprintf(stdout,"\n");
+
+  // status file
+  report_stats(params, stats, bit_use, frame_rate);
+
+  // write to log file
+  report_log(params, stats, frame_rate);
+
+  if (params->ReportFrameStats)
+  {
+    if ((p_log = fopen("stat_frame.dat", "a")) == NULL)       // append new statistic at the end
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "stat_frame.dat.dat");
+      //    error(errortext, 500);
+    }
+    else
+    {
+      fprintf(p_log," --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+      fclose(p_log);
+    }
+    report_log_mode(params, stats, bit_use);
+  }
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Prints the header of the protocol.
+ * \par Input:
+ *    struct inp_par *inp
+ * \par Output:
+ *    none
+ ************************************************************************
+ */
+void information_init ( ImageParameters *img, InputParameters *params, StatParameters *stats)
+{
+  int i;
+  static char yuv_types[4][10] = {"YUV 4:0:0", "YUV 4:2:0", "YUV 4:2:2", "YUV 4:4:4"};
+  switch (params->Verbose)
+  {
+  case 0:
+  case 1:
+  default:
+    printf("------------------------------- JM %4.4s %7.7s -------------------------------\n", VERSION, EXT_VERSION);
+    break;
+  case 2:
+    printf("--------------------------------------- JM %4.4s %7.7s ----------------------------------------\n", VERSION, EXT_VERSION);
+    break;
+  }
+
+  fprintf(stdout,  " Input YUV file                    : %s \n", params->infile);
+  fprintf(stdout,  " Output H.264 bitstream            : %s \n", params->outfile);
+  if (p_dec != -1)
+    fprintf(stdout,  " Output YUV file                   : %s \n", params->ReconFile);
+  fprintf(stdout,  " YUV Format                        : %s \n", &yuv_types[img->yuv_format][0]);//img->yuv_format==YUV422?"YUV 4:2:2":(img->yuv_format==YUV444)?"YUV 4:4:4":"YUV 4:2:0");
+  fprintf(stdout,  " Frames to be encoded I-P/B        : %d/%d\n", params->no_frames, (params->successive_Bframe*(params->no_frames-1)));
+  if (params->Verbose != 0)
+  {
+    fprintf(stdout,  " Freq. for encoded bitstream       : %1.0f\n", img->framerate/(float)(params->jumpd+1));
+    fprintf(stdout,  " PicInterlace / MbInterlace        : %d/%d\n", params->PicInterlace, params->MbInterlace);
+    fprintf(stdout,  " Transform8x8Mode                  : %d\n", params->Transform8x8Mode);
+
+    for (i=0; i<3; i++)
+    {
+      fprintf(stdout," ME Metric for Refinement Level %1d  : %s\n", i, DistortionType[params->MEErrorMetric[i]]);
+    }
+    fprintf(stdout,  " Mode Decision Metric              : %s\n", DistortionType[params->ModeDecisionMetric]);
+
+    switch ( params->ChromaMEEnable )
+    {
+    case 1:
+      fprintf(stdout," Motion Estimation for components  : YCbCr\n");
+      break;
+    default:
+      fprintf(stdout," Motion Estimation for components  : Y\n");
+      break;
+    }
+
+    fprintf(stdout,  " Image format                      : %dx%d (%dx%d)\n", params->output.width, params->output.height, img->width,img->height);
+
+    if (params->intra_upd)
+      fprintf(stdout," Error robustness                  : On\n");
+    else
+      fprintf(stdout," Error robustness                  : Off\n");
+    fprintf(stdout,  " Search range                      : %d\n", params->search_range);
+
+    fprintf(stdout,  " Total number of references        : %d\n", params->num_ref_frames);
+    fprintf(stdout,  " References for P slices           : %d\n", params->P_List0_refs ? params->P_List0_refs : params->num_ref_frames);
+    fprintf(stdout,  " List0 references for B slices     : %d\n", params->B_List0_refs ? params->B_List0_refs : params->num_ref_frames);
+    fprintf(stdout,  " List1 references for B slices     : %d\n", params->B_List1_refs ? params->B_List1_refs : params->num_ref_frames);
+
+    // Sequence Type
+    fprintf(stdout,  " Sequence type                     :");
+    if (stats->successive_Bframe > 0 && params->HierarchicalCoding)
+    {
+      fprintf(stdout, " Hierarchy (QP: I %d, P %d, B %d) \n",
+        params->qp0, params->qpN, params->qpB);
+    }
+    else if (stats->successive_Bframe > 0)
+    {
+      char seqtype[80];
+      int i,j;
+
+      strcpy (seqtype,"I");
+
+      for (j=0; j < 2; j++)
+      {
+        for (i=0; i < stats->successive_Bframe; i++)
+        {
+          if (params->BRefPictures)
+            strncat(seqtype,"-RB", imax(0, (int) (79 - strlen(seqtype))));
+          else
+            strncat(seqtype,"-B", imax(0, (int) (79 - strlen(seqtype))));
+        }
+        strncat(seqtype,"-P", imax(0, (int) (79 - strlen(seqtype))));
+      }
+      if (params->BRefPictures)
+        fprintf(stdout, " %s (QP: I %d, P %d, RB %d) \n", seqtype, params->qp0, params->qpN, iClip3(0, 51, params->qpB + params->qpBRSOffset));
+      else
+        fprintf(stdout, " %s (QP: I %d, P %d, B %d) \n", seqtype, params->qp0, params->qpN, params->qpB);
+    }
+    else if (stats->successive_Bframe == 0 && params->sp_periodicity == 0) 
+      fprintf(stdout, " IPPP (QP: I %d, P %d) \n", params->qp0, params->qpN);
+    else 
+      fprintf(stdout, " I-P-P-SP-P (QP: I %d, P %d, SP (%d, %d)) \n",  params->qp0, params->qpN, params->qpsp, params->qpsp_pred);
+
+    // report on entropy coding  method
+    if (params->symbol_mode == CAVLC)
+      fprintf(stdout," Entropy coding method             : CAVLC\n");
+    else
+      fprintf(stdout," Entropy coding method             : CABAC\n");
+
+    fprintf(stdout,  " Profile/Level IDC                 : (%d,%d)\n", params->ProfileIDC, params->LevelIDC);
+
+    if (params->SearchMode == UM_HEX)
+      fprintf(stdout,  " Motion Estimation Scheme          : HEX\n");
+    else if (params->SearchMode == UM_HEX_SIMPLE)
+      fprintf(stdout,  " Motion Estimation Scheme          : SHEX\n");
+    else if (params->SearchMode == EPZS)
+    {
+      fprintf(stdout,  " Motion Estimation Scheme          : EPZS\n");
+      EPZSOutputStats(params, stdout, 0);
+    }
+    else if (params->SearchMode == FAST_FULL_SEARCH)
+      fprintf(stdout,  " Motion Estimation Scheme          : Fast Full Search\n");
+    else
+      fprintf(stdout,  " Motion Estimation Scheme          : Full Search\n");
+
+    if (params->full_search == 2)
+      fprintf(stdout," Search range restrictions         : none\n");
+    else if (params->full_search == 1)
+      fprintf(stdout," Search range restrictions         : older reference frames\n");
+    else
+      fprintf(stdout," Search range restrictions         : smaller blocks and older reference frames\n");
+
+    if (params->rdopt)
+      fprintf(stdout," RD-optimized mode decision        : used\n");
+    else
+      fprintf(stdout," RD-optimized mode decision        : not used\n");
+
+    switch(params->partition_mode)
+    {
+    case PAR_DP_1:
+      fprintf(stdout," Data Partitioning Mode            : 1 partition \n");
+      break;
+    case PAR_DP_3:
+      fprintf(stdout," Data Partitioning Mode            : 3 partitions \n");
+      break;
+    default:
+      fprintf(stdout," Data Partitioning Mode            : not supported\n");
+      break;
+    }
+
+    switch(params->of_mode)
+    {
+    case PAR_OF_ANNEXB:
+      fprintf(stdout," Output File Format                : H.264/AVC Annex B Byte Stream Format \n");
+      break;
+    case PAR_OF_RTP:
+      fprintf(stdout," Output File Format                : RTP Packet File Format \n");
+      break;
+    default:
+      fprintf(stdout," Output File Format                : not supported\n");
+      break;
+    }
+  }
+
+
+  switch (params->Verbose)
+  {
+  case 0:
+  default:
+    printf("-------------------------------------------------------------------------------\n");
+    printf("\nEncoding. Please Wait.\n\n");
+    break;    
+  case 1:
+    printf("-------------------------------------------------------------------------------\n");
+    printf("  Frame  Bit/pic    QP   SnrY    SnrU    SnrV    Time(ms) MET(ms) Frm/Fld Ref  \n");
+    printf("-------------------------------------------------------------------------------\n");
+    break;
+  case 2:
+    if (params->Distortion[SSIM] == 1)
+    {
+      printf("------------------------------------------------------------------------------------------------------------------------\n");
+      printf("  Frame  Bit/pic WP QP QL   SnrY    SnrU    SnrV   SsimY   SsimU   SsimV    Time(ms) MET(ms) Frm/Fld   I D L0 L1 RDP Ref\n");
+      printf("------------------------------------------------------------------------------------------------------------------------\n");
+    }
+    else
+    {
+      printf("------------------------------------------------------------------------------------------------\n");
+      printf("  Frame  Bit/pic WP QP QL   SnrY    SnrU    SnrV    Time(ms) MET(ms) Frm/Fld   I D L0 L1 RDP Ref\n");
+      printf("------------------------------------------------------------------------------------------------\n");
+    }
+    break;
+   
+  }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Report mode distribution of the sequence to log_mode.dat
+ ************************************************************************
+ */
+void report_log_mode(InputParameters *params, StatParameters *stats, int64 bit_use[NUM_SLICE_TYPES][2])
+{
+  FILE *p_stat;                    //!< status file for the last encoding session
+  int i;
+  char name[40];
+#ifndef WIN32
+  time_t now;
+  struct tm *l_time;
+  char string[1000];
+#else
+  char timebuf[128];
+#endif
+
+  if ((p_stat = fopen("log_mode.dat", "r")) == 0)         // check if file exists
+  {
+    if ((p_stat = fopen("log_mode.dat", "a")) == NULL)    // append new statistic at the end
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log_mode.dat");
+      error(errortext, 500);
+    }
+    else                                            // Create header for new log file
+    {
+      fprintf(p_stat, " ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+      fprintf(p_stat,"|                          Encoder statistics. This file is generated during first encoding session, new sessions will be appended                                                                                                                                                                                 |\n");
+      fprintf(p_stat, " ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+      fprintf(p_stat, "|     ver     | Date  | Time  |    Sequence                  | QP |  I4  |  I8  | I16  | IC0  | IC1  | IC2  | IC3  | PI4  | PI8  | PI16 |  P0  |  P1  |  P2  |  P3  | P1*4*| P1*8*| P2*4*| P2*8*| P3*4*| P3*8*|  P8  | P8:4 | P4*4*| P4*8*| P8:5 | P8:6 | P8:7 | BI4  | BI8  | BI16 |  B0  |  B1  |  B2  |  B3  | B0*4*| B0*8*| B1*4*| B1*8*| B2*4*| B2*8*| B3*4*| B3*8*|  B8  | B8:0 |B80*4*|B80*8*| B8:4 | B4*4*| B4*8*| B8:5 | B8:6 | B8:7 |\n");
+      fprintf(p_stat, " ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
+    }
+  }
+  else
+  {
+    fclose (p_stat);
+    if ((p_stat = fopen("log_mode.dat", "a")) == NULL)         // File exists, just open for appending
+    {
+      snprintf(errortext, ET_SIZE, "Error open file %s  \n", "log_mode.dat");
+      error(errortext, 500);
+    }
+  }
+
+  //report
+  fprintf(p_stat, "|%4s/%s", VERSION, EXT_VERSION);
+
+#ifdef WIN32
+  _strdate( timebuf );
+  fprintf(p_stat, "| %1.5s |", timebuf);
+
+  _strtime( timebuf);
+  fprintf(p_stat, " % 1.5s |", timebuf);
+#else
+  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
+  time (&now);
+  l_time = localtime (&now);
+  strftime (string, sizeof string, "%d-%b-%Y", l_time);
+  fprintf(p_stat, "| %1.5s |", string );
+
+  strftime (string, sizeof string, "%H:%M:%S", l_time);
+  fprintf(p_stat, " %1.5s |", string);
+#endif
+
+  for (i=0;i<30;i++)
+    name[i]=params->infile[i + imax(0,(int) (strlen(params->infile)- 30))]; // write last part of path, max 30 chars
+
+  fprintf(p_stat, "%30.30s|", name);
+  fprintf(p_stat, "%3d |", img->qp);
+
+  //report modes
+  //I-Modes
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I4MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I8MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[I_SLICE][I16MB]);
+
+  //chroma intra mode
+  fprintf(p_stat, " %5d|", stats->intra_chroma_mode[0]);
+  fprintf(p_stat, " %5d|", stats->intra_chroma_mode[1]);
+  fprintf(p_stat, " %5d|", stats->intra_chroma_mode[2]);
+  fprintf(p_stat, " %5d|", stats->intra_chroma_mode[3]);
+
+  //P-Modes
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I4MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I8MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][I16MB]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][0    ]);
+
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][1    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][2    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][3    ]);
+  
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][1][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][1][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][2][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][2][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][3][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][3][1]);
+
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][P8x8 ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][4    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][4][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[P_SLICE][4][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][5    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][6    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[P_SLICE][7    ]);
+
+  //B-Modes
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I4MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I8MB ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][I16MB]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][0    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][1    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][2    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][3    ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][0][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][0][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][1][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][1][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][2][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][2][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][3][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][3][1]);
+
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][P8x8]);
+  fprintf(p_stat, " %d|", (stats->b8_mode_0_use [B_SLICE][0]+stats->b8_mode_0_use [B_SLICE][1]));
+  fprintf(p_stat, " %5d|", stats->b8_mode_0_use [B_SLICE][0]);
+  fprintf(p_stat, " %5d|", stats->b8_mode_0_use [B_SLICE][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][4   ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][4][0]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use_transform[B_SLICE][4][1]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][5   ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][6   ]);
+  fprintf(p_stat, " %5" FORMAT_OFF_T  "|", stats->mode_use[B_SLICE][7   ]);
+
+  fprintf(p_stat, "\n");
+  fclose(p_stat);
+}
+
+
diff --git a/lencod/src/slice.c b/lencod/src/slice.c
index d7aaa35..dfbbfd8 100644
--- a/lencod/src/slice.c
+++ b/lencod/src/slice.c
@@ -32,23 +32,26 @@
 #include "macroblock.h"
 #include "symbol.h"
 #include "context_ini.h"
+#include "enc_statistics.h"
 #include "ratectl.h"
 #include "me_epzs.h"
 #include "wp.h"
+#include "slice.h"
 
 #include "q_offsets.h"
 #include "conformance.h"
 
 #include "rdo_quant.h"
+#include "wp_mcprec.h"
+
 
 // Local declarations
 static Slice *malloc_slice();
 static void  free_slice(Slice *slice);
-
 static void  set_ref_pic_num();
+
 extern ColocatedParams *Co_located;
 extern StorablePicture **listX[6];
-void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no);
 
 //! convert from H.263 QP to H.264 quant given by: quant=pow(2,QP/6)
 const int QP2QUANT[40]=
@@ -137,8 +140,6 @@ int start_slice()
   return header_len;
 }
 
-
-
 /*!
  ************************************************************************
  * \brief
@@ -300,6 +301,7 @@ int encode_one_slice (int SliceGroupId, Picture *pic, int TotalCodedMBs)
       }
       else
       {
+        img->masterQP = img->qp;
         encode_one_macroblock (currMB);
         write_one_macroblock (currMB, 1, prev_recode_mb);    
       }
@@ -645,9 +647,9 @@ void init_slice (int start_mb_addr)
 
   img->currentSlice = currSlice;
 
-  currSlice->picture_id = img->tr % 256;
-  currSlice->qp = img->qp;
-  currSlice->start_mb_nr = start_mb_addr;
+  currSlice->picture_id    = img->tr % 256;
+  currSlice->qp            = img->qp;
+  currSlice->start_mb_nr   = start_mb_addr;
   currSlice->slice_too_big = dummy_slice_too_big;
 
   for (i = 0; i < currSlice->max_part_nr; i++)
@@ -700,11 +702,25 @@ void init_slice (int start_mb_addr)
   img->num_ref_idx_l0_active = listXsize[0];
   img->num_ref_idx_l1_active = listXsize[1];
 
-  //Perform memory management based on poc distances
-  //if (img->nal_reference_idc  && params->HierarchicalCoding && params->PocMemoryManagement && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
-  if (img->nal_reference_idc  && params->PocMemoryManagement && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
+  if ( params->WPMCPrecision && params->WPMCPrecFullRef )
   {
-    poc_based_ref_management(img->frame_num);
+    wpxAdaptRefNum(img);
+  }
+
+  //Perform memory management based on poc distances  
+
+  if (img->nal_reference_idc && params->PocMemoryManagement)
+  {
+    if (img->structure == FRAME && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
+    {
+      poc_based_ref_management_frame_pic(img->frame_num);
+    }
+    else if (img->structure == TOP_FIELD && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
+    {
+      poc_based_ref_management_field_pic((img->frame_num << 1) + 1);      
+    }
+    else if (img->structure == BOTTOM_FIELD)
+      poc_based_ref_management_field_pic((img->frame_num << 1) + 1);
   }
 
   if (params->EnableOpenGOP)
@@ -730,32 +746,48 @@ void init_slice (int start_mb_addr)
 
   init_ref_pic_list_reordering();
  
-  // Perform reordering based on poc distances for HierarchicalCoding
-  if ( img->type == P_SLICE && params->ReferenceReorder)
+  // reference list reordering 
+  if ( (img->type == P_SLICE || img->type == B_SLICE) && 
+    params->WPMCPrecision && pWPX->curr_wp_rd_pass->algorithm != WP_REGULAR )
   {
-    int i, num_ref;
+    wpxReorderLists( img, currSlice );
+  }
+  else
+  {
+    // Perform reordering based on poc distances for HierarchicalCoding
+    if ( img->type == P_SLICE && params->ReferenceReorder)
+    {
+      int i, num_ref;
 
-    alloc_ref_pic_list_reordering_buffer(currSlice);
+      alloc_ref_pic_list_reordering_buffer(currSlice);
 
-    for (i = 0; i < img->num_ref_idx_l0_active + 1; i++)
-    {
-      currSlice->reordering_of_pic_nums_idc_l0[i] = 3;
-      currSlice->abs_diff_pic_num_minus1_l0[i] = 0;
-      currSlice->long_term_pic_idx_l0[i] = 0;
-    }
+      for (i = 0; i < img->num_ref_idx_l0_active + 1; i++)
+      {
+        currSlice->reordering_of_pic_nums_idc_l0[i] = 3;
+        currSlice->abs_diff_pic_num_minus1_l0[i] = 0;
+        currSlice->long_term_pic_idx_l0[i] = 0;
+      }
 
-    num_ref = img->num_ref_idx_l0_active;
-
-    poc_ref_pic_reorder(listX[LIST_0], num_ref,
-      currSlice->reordering_of_pic_nums_idc_l0,
-      currSlice->abs_diff_pic_num_minus1_l0,
-      currSlice->long_term_pic_idx_l0, LIST_0);
-    // reference picture reordering
-    reorder_ref_pic_list(listX[LIST_0], &listXsize[LIST_0],
-      img->num_ref_idx_l0_active - 1,
-      currSlice->reordering_of_pic_nums_idc_l0,
-      currSlice->abs_diff_pic_num_minus1_l0,
-      currSlice->long_term_pic_idx_l0);
+      num_ref = img->num_ref_idx_l0_active;
+      if ( img->structure == FRAME )
+      poc_ref_pic_reorder_frame(listX[LIST_0], num_ref,
+        currSlice->reordering_of_pic_nums_idc_l0,
+        currSlice->abs_diff_pic_num_minus1_l0,
+        currSlice->long_term_pic_idx_l0, LIST_0);
+      else
+      {
+        poc_ref_pic_reorder_field(listX[LIST_0], num_ref,
+          currSlice->reordering_of_pic_nums_idc_l0,
+          currSlice->abs_diff_pic_num_minus1_l0,
+          currSlice->long_term_pic_idx_l0, LIST_0);
+      }
+      //reference picture reordering
+      reorder_ref_pic_list(listX[LIST_0], &listXsize[LIST_0],
+        img->num_ref_idx_l0_active - 1,
+        currSlice->reordering_of_pic_nums_idc_l0,
+        currSlice->abs_diff_pic_num_minus1_l0,
+        currSlice->long_term_pic_idx_l0);
+    }
   }
 
   //if (img->MbaffFrameFlag)
@@ -769,10 +801,10 @@ void init_slice (int start_mb_addr)
     if (img->type==P_SLICE || img->type==SP_SLICE)
     {
       int wp_type = (params->GenerateMultiplePPS && params->RDPictureDecision) && (enc_picture != enc_frame_picture[1]);
-      EstimateWPPSlice (wp_type);
+      EstimateWPPSlice (img, params, wp_type);
     }
     else
-       EstimateWPBSlice ();
+      EstimateWPBSlice (img, params);
   }
 
   set_ref_pic_num();
@@ -790,7 +822,7 @@ void init_slice (int start_mb_addr)
   }
 
   if (img->type != I_SLICE && params->SearchMode == EPZS)
-    EPZSSliceInit(EPZSCo_located, listX);
+    EPZSSliceInit(params, img, EPZSCo_located, listX);
 
   if (params->symbol_mode == CAVLC)
   {
@@ -802,19 +834,20 @@ void init_slice (int start_mb_addr)
       switch (listXsize[i])
       {
       case 0:
-        writeRefFrame[i]     = NULL;
+        writeRefFrame[i]   = NULL;
         break;
       case 1:
-        writeRefFrame[i]     = writeSE_Dummy;
+        writeRefFrame[i]   = writeSE_Dummy;
         break;
       case 2:
-        writeRefFrame[i]     = writeSE_invFlag;
+        writeRefFrame[i]   = writeSE_invFlag;
         break;
       default:
-        writeRefFrame[i]     = writeSE_UVLC;
+        writeRefFrame[i]   = writeSE_UVLC;
         break;
       }
     }
+
     writeMVD               = writeSE_SVLC;
     writeCBP               = writeCBP_VLC;
     writeDquant            = writeSE_SVLC;
@@ -832,12 +865,12 @@ void init_slice (int start_mb_addr)
       switch (listXsize[i])
       {
       case 0:
-        writeRefFrame[i]     = NULL;
+        writeRefFrame[i]   = NULL;
       case 1:
-        writeRefFrame[i]     = writeSE_Dummy;
+        writeRefFrame[i]   = writeSE_Dummy;
         break;
       default:
-        writeRefFrame[i]     = writeRefFrame_CABAC;
+        writeRefFrame[i]   = writeRefFrame_CABAC;
       }
     }
     writeMVD               = writeMVD_CABAC;
@@ -1001,7 +1034,7 @@ static void free_slice(Slice *slice)
   }
 }
 
-void set_ref_pic_num()
+static void set_ref_pic_num()
 {
   int i,j;
   StorablePicture *this_ref;
@@ -1020,7 +1053,7 @@ void set_ref_pic_num()
   for (i=0;i<listXsize[LIST_1];i++)
   {
     this_ref = listX[LIST_1][i];
-    enc_picture->ref_pic_num        [LIST_1][i] = this_ref->poc  *2 + ((this_ref->structure==BOTTOM_FIELD)?1:0);
+    enc_picture->ref_pic_num        [LIST_1][i] = this_ref->poc * 2 + ((this_ref->structure==BOTTOM_FIELD)?1:0);
     enc_picture->frm_ref_pic_num    [LIST_1][i] = this_ref->frame_poc * 2;
     enc_picture->top_ref_pic_num    [LIST_1][i] = this_ref->top_poc * 2;
     enc_picture->bottom_ref_pic_num [LIST_1][i] = this_ref->bottom_poc * 2 + 1;
@@ -1046,9 +1079,9 @@ void set_ref_pic_num()
 *    decide reference picture reordering, Frame only
 ************************************************************************
 */
-void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no)
+void poc_ref_pic_reorder_frame(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no)
 {
-  unsigned i,j,k;
+  unsigned int i,j,k;
 
   int currPicNum, picNumLXPred;
 
@@ -1062,17 +1095,10 @@ void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active,
 
   int abs_poc_dist;
   int maxPicNum;
+  unsigned int numRefs;
 
-  if (img->structure==FRAME)
-  {
-    maxPicNum  = max_frame_num;
-    currPicNum = img->frame_num;
-  }
-  else
-  {
-    maxPicNum  = 2 * max_frame_num;
-    currPicNum = 2 * img->frame_num + 1;
-  }
+  maxPicNum  = max_frame_num;
+  currPicNum = img->frame_num;
 
   picNumLXPred = currPicNum;
 
@@ -1086,8 +1112,10 @@ void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active,
   // to a potential reordering list. For each one of these
   // references compute the poc distance compared to current
   // frame.
+  numRefs = dpb.ref_frames_in_buffer;
   for (i=0; i<dpb.ref_frames_in_buffer; i++)
   {
+    poc_diff[i] = 0xFFFF;
     re_order[i] = dpb.fs_ref[i]->frame->pic_num;
 
     if (dpb.fs_ref[i]->is_used==3 && (dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
@@ -1106,9 +1134,9 @@ void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active,
   }
 
   // now sort these references based on poc (temporal) distance
-  for (i=0; i< dpb.ref_frames_in_buffer-1; i++)
+  for (i = 0; i< numRefs - 1; i++)
   {
-    for (j=i+1; j< dpb.ref_frames_in_buffer; j++)
+    for (j = i + 1; j < numRefs; j++)
     {
       if (poc_diff[i]>poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
       {
@@ -1125,6 +1153,16 @@ void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active,
       }
     }
   }
+  // populate list with selections from the pre-analysis stage
+  if ( params->WPMCPrecision 
+    && pWPX->curr_wp_rd_pass->algorithm != WP_REGULAR
+    && pWPX->num_wp_ref_list[list_no] )
+  {
+    for (i=0; i<num_ref_idx_lX_active; i++)
+    {
+      re_order[i] = pWPX->wp_ref_list[list_no][i].PicNum;
+    }
+  }
 
   // Check versus default list to see if any
   // change has happened
@@ -1203,118 +1241,311 @@ void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active,
   }
 }
 
+/*!
+************************************************************************
+* \brief
+*    decide reference picture reordering, Field only
+************************************************************************
+*/
+void poc_ref_pic_reorder_field(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no)
+{
+  unsigned int i,j,k;
 
+  int currPicNum, picNumLXPred;
 
-void SetLagrangianMultipliers()
-{
-  int qp, j, k;
-  double qp_temp;
-  double lambda_scale = 1.0 - dClip3(0.0,0.5,0.05 * (double) params->jumpd);;
+  int default_order[32];
+  int re_order[32];
+  int tmp_reorder[32];
+  int list_sign[32];  
+  int poc_diff[32];
+  int fld_type[32];
+
+  int reorder_stop, no_reorder;
+  int tmp_value, diff;
 
-  if (params->rdopt) // RDOPT on computation of Lagrangian multipliers
+  int abs_poc_dist;
+  int maxPicNum;
+  unsigned int numRefs;
+
+  int field_used[2] = {1, 2};
+  int fld, idx, num_flds;
+
+  unsigned int top_idx = 0;
+  unsigned int bot_idx = 0;
+  unsigned int list_size = 0;
+
+  StorablePicture *pField[2]; // 0: TOP_FIELD, 1: BOTTOM_FIELD
+  FrameStore      *pFrameStore; 
+
+  maxPicNum  = 2 * max_frame_num;
+  currPicNum = 2 * img->frame_num + 1;
+
+  picNumLXPred = currPicNum;
+
+  // First assign default list order.
+  for (i=0; i<num_ref_idx_lX_active; i++)
   {
-    for (j = 0; j < 5; j++)
+    default_order[i] = list[i]->pic_num;
+  }
+
+  // Now access all references in buffer and assign them
+  // to a potential reordering list. For each one of these
+  // references compute the poc distance compared to current
+  // frame.  
+  // look for eligible fields
+  idx = 0;
+
+  for (i=0; i<dpb.ref_frames_in_buffer; i++)
+  {
+    pFrameStore = dpb.fs_ref[i];
+    pField[0]   = pFrameStore->top_field;
+    pField[1]   = pFrameStore->bottom_field;
+    num_flds    = (img->structure == BOTTOM_FIELD && (enc_picture->poc == (pField[0]->poc + 1) ) ) ? 1 : 2;
+
+    poc_diff[2*i    ] = 0xFFFF;
+    poc_diff[2*i + 1] = 0xFFFF;
+
+    for ( fld = 0; fld < num_flds; fld++ )
     {
-      for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
+      if ( (pFrameStore->is_used & field_used[fld]) && pField[fld]->used_for_reference && !(pField[fld]->is_long_term) )
       {
-        qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
+        abs_poc_dist = iabs(pField[fld]->poc - enc_picture->poc) ;
+        poc_diff[idx] = abs_poc_dist;
+        re_order[idx] = pField[fld]->pic_num;
+        fld_type[idx] = fld + 1;
 
-        if (params->UseExplicitLambdaParams == 1) // consideration of explicit lambda weights.
+        if (list_no == LIST_0)
         {
-          img->lambda_md[j][qp] = params->LambdaWeight[j] * pow (2, qp_temp/3.0);
-          // Scale lambda due to hadamard qpel only consideration
-          img->lambda_md[j][qp] = ( (params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
-
-          for (k = F_PEL; k <= Q_PEL; k++)
-          {
-            img->lambda_me[j][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
-            img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
-          }
+          list_sign[idx] = (enc_picture->poc < pField[fld]->poc) ? +1 : -1;
+        }
+        else
+        {
+          list_sign[idx] = (enc_picture->poc > pField[fld]->poc) ? +1 : -1;
+        }
+        idx++;
+      }
+    }
+  }
+  numRefs = idx;
 
-          if (j == B_SLICE)
-          {
-            img->lambda_md[5][qp] = params->LambdaWeight[5] * pow (2, qp_temp/3.0);
-            img->lambda_md[5][qp] = ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[5][qp];
+  // now sort these references based on poc (temporal) distance
+  for (i=0; i < numRefs-1; i++)
+  {
+    for (j = (i + 1); j < numRefs; j++)
+    {
+      if (poc_diff[i] > poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
+      {
+        // poc_diff
+        tmp_value   = poc_diff[i];
+        poc_diff[i] = poc_diff[j];
+        poc_diff[j] = tmp_value;
+        // re_order (PicNum)
+        tmp_value   = re_order[i];
+        re_order[i] = re_order[j];
+        re_order[j] = tmp_value;
+        // list_sign
+        tmp_value    = list_sign[i];
+        list_sign[i] = list_sign[j];
+        list_sign[j] = tmp_value;
+        // fld_type
+        tmp_value   = fld_type[i];
+        fld_type[i] = fld_type[j];
+        fld_type[j] = tmp_value ;
+      }
+    }
+  }
 
-            for (k = F_PEL; k <= Q_PEL; k++)
-            {
-              img->lambda_me[5][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
-              img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
-            }
-          }
+  if (img->structure == TOP_FIELD)
+  {
+    while ((top_idx < numRefs)||(bot_idx < numRefs))
+    {
+      for ( ; top_idx < numRefs; top_idx++)
+      {
+        if ( fld_type[top_idx] == TOP_FIELD )
+        {
+          tmp_reorder[list_size] = re_order[top_idx];
+          list_size++;
+          top_idx++;
+          break;
         }
-        else if (params->UseExplicitLambdaParams == 2) // consideration of fixed lambda values.
+      }
+      for ( ; bot_idx < numRefs; bot_idx++)
+      {
+        if ( fld_type[bot_idx] == BOTTOM_FIELD )
+        {
+          tmp_reorder[list_size] = re_order[bot_idx];
+          list_size++;
+          bot_idx++;
+          break;
+        }
+      }
+    }
+  }
+  if (img->structure == BOTTOM_FIELD)
+  {
+    while ((top_idx < numRefs)||(bot_idx < numRefs))
+    {
+      for ( ; bot_idx < numRefs; bot_idx++)
+      {
+        if ( fld_type[bot_idx] == BOTTOM_FIELD )
         {
-          img->lambda_md[j][qp] = params->FixedLambda[j];
-          // Scale lambda due to hadamard qpel only consideration
-          img->lambda_md[j][qp] = ( (params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
+          tmp_reorder[list_size] = re_order[bot_idx];
+          list_size++;
+          bot_idx++;
+          break;
+        }
+      }
+      for ( ; top_idx < numRefs; top_idx++)
+      {
+        if ( fld_type[top_idx] == TOP_FIELD )
+        {
+          tmp_reorder[list_size] = re_order[top_idx];
+          list_size++;
+          top_idx++;
+          break;
+        }
+      }
+    }
+  }
 
-          for (k = F_PEL; k <= Q_PEL; k++)
-          {
-            img->lambda_me[j][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
-            img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
-          }
+  // copy to final matrix
+  list_size = imin( list_size, 32 );
+  for ( i = 0; i < list_size; i++ )
+  {
+    re_order[i] = tmp_reorder[i];
+  }
 
-          if (j == B_SLICE)
-          {
-            img->lambda_md[5][qp] = params->FixedLambda[5];
-            img->lambda_md[5][qp] = ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[5][qp];
+  // Check versus default list to see if any
+  // change has happened
+  no_reorder = 1;
+  for (i=0; i<num_ref_idx_lX_active; i++)
+  {
+    if (default_order[i] != re_order[i])
+    {
+      no_reorder = 0;
+    }
+  }
 
-            for (k = F_PEL; k <= Q_PEL; k++)
-            {
-              img->lambda_me[5][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
-              img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
-            }
-          }
+  // If different, then signal reordering
+  if (no_reorder == 0)
+  {
+    for (i=0; i<num_ref_idx_lX_active; i++)
+    {
+      diff = re_order[i] - picNumLXPred;
+      if (diff <= 0)
+      {
+        reordering_of_pic_nums_idc[i] = 0;
+        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
+        if (abs_diff_pic_num_minus1[i] < 0)
+          abs_diff_pic_num_minus1[i] = maxPicNum -1;
+      }
+      else
+      {
+        reordering_of_pic_nums_idc[i] = 1;
+        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
+      }
+      picNumLXPred = re_order[i];
+
+      tmp_reorder[i] = re_order[i];
+
+      k = i;
+      for (j = i; j < num_ref_idx_lX_active; j++)
+      {
+        if (default_order[j] != re_order[i])
+        {
+          ++k;
+          tmp_reorder[k] = default_order[j];
         }
-        else
+      }
+      reorder_stop = 1;
+      for(j=i+1; j<num_ref_idx_lX_active; j++)
+      {
+        if (tmp_reorder[j] != re_order[j])
         {
-          if (params->successive_Bframe>0)
-            img->lambda_md[j][qp] = 0.68 * pow (2, qp_temp/3.0)
-            * (j == B_SLICE ? dClip3(2.00,4.00,(qp_temp / 6.0)) : (j == SP_SLICE) ? dClip3(1.4,3.0,(qp_temp / 12.0)) : 1.0);
-          else
-            img->lambda_md[j][qp] = 0.85 * pow (2, qp_temp/3.0)
-            * ( (j == B_SLICE) ? 4.0 : (j == SP_SLICE) ? dClip3(1.4,3.0,(qp_temp / 12.0)) : 1.0);
-          // Scale lambda due to hadamard qpel only consideration
-          img->lambda_md[j][qp] = ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
-          img->lambda_md[j][qp] = (j == B_SLICE && params->BRefPictures == 2 && img->b_frame_to_code == 0 ? 0.50 : 1.00) * img->lambda_md[j][qp];
-
-          if (j == B_SLICE)
-          {
-            img->lambda_md[5][qp] = img->lambda_md[j][qp];
+          reorder_stop = 0;
+          break;
+        }
+      }
 
-            if (params->HierarchicalCoding == 2)
-              img->lambda_md[5][qp] *= (1.0 - dmin(0.4,0.2 * (double) gop_structure[img->b_frame_to_code-1].hierarchy_layer)) ;
-            else
-              img->lambda_md[5][qp] *= 0.80;
+      if (reorder_stop==1)
+      {
+        ++i;
+        break;
+      }
 
-            img->lambda_md[5][qp] *= lambda_scale;
+      memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));
+    }
+    reordering_of_pic_nums_idc[i] = 3;
 
-            for (k = F_PEL; k <= Q_PEL; k++)
-            {
-              img->lambda_me[5][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
-              img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
-            }
-          }
-          else
-            img->lambda_md[j][qp] *= lambda_scale;
+    memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));
 
-          for (k = F_PEL; k <= Q_PEL; k++)
-          {
-            img->lambda_me[j][qp][k] = params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
-            img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
-          }
+    if (list_no==0)
+    {
+      img->currentSlice->ref_pic_list_reordering_flag_l0 = 1;
+    }
+    else
+    {
+      img->currentSlice->ref_pic_list_reordering_flag_l1 = 1;
+    }
+  }
+}
 
-          if (params->CtxAdptLagrangeMult == 1)
+void UpdateMELambda(ImageParameters *img)
+{
+  int j, k, qp;
+  if (params->UpdateLambdaChromaME)
+  {
+    for (j = 0; j < 6; j++)
+    {
+      for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
+      { 
+        for (k = 0; k < 3; k++)
+        {
+          if ((params->MEErrorMetric[k] == ERROR_SAD) && (params->ChromaMEEnable))
           {
-            int lambda_qp = (qp >= 32 && !params->RCEnable) ? imax(0, qp - 4) : imax(0, qp - 6);
-            img->lambda_mf_factor[j][qp] = log (img->lambda_me[j][lambda_qp][Q_PEL] + 1.0) / log (2.0);
+            switch(params->yuv_format)
+            {
+            case YUV420:
+              img->lambda_mf[j][qp][k] = (3 * img->lambda_mf[j][qp][k] + 1) >> 1;
+              img->lambda_me[j][qp][k] *= 1.5;
+              break;
+            case YUV422:
+              img->lambda_mf[j][qp][k] *= 2;
+              img->lambda_me[j][qp][k] *= 2.0;
+              break;
+            case YUV444:
+              img->lambda_mf[j][qp][k] *= 3;
+              img->lambda_me[j][qp][k] *= 3.0;
+              break;
+            default:
+              break;
+            }
           }
         }
       }
     }
   }
-  else // RDOPT off computation of Lagrangian multipliers
+}
+
+void SetLambda(int j, int qp, double lambda_scale)
+{
+  int k;
+  img->lambda_md[j][qp] *= lambda_scale;
+
+  for (k = F_PEL; k <= Q_PEL; k++)
+  {
+    img->lambda_me[j][qp][k] =  (params->MEErrorMetric[k] == ERROR_SSE) ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
+    img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
+  }
+}
+
+void SetLagrangianMultipliersOn()
+{
+  int qp, j;
+  double qp_temp;
+  double lambda_scale = 1.0 - dClip3(0.0,0.5,0.05 * (double) params->jumpd);;
+
+  if (params->UseExplicitLambdaParams == 1) // consideration of explicit lambda weights.
   {
     for (j = 0; j < 6; j++)
     {
@@ -1322,32 +1553,110 @@ void SetLagrangianMultipliers()
       {
         qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
 
-        if (params->UseExplicitLambdaParams == 1) // consideration of explicit lambda weights.
-        {
-          img->lambda_md[j][qp] = sqrt(params->LambdaWeight[j] * pow (2, qp_temp/3.0));
-        }
-        else if (params->UseExplicitLambdaParams == 2) // consideration of explicit lambda
-        {
-          img->lambda_md[j][qp] = sqrt(params->FixedLambda[j]);
-        }
+        img->lambda_md[j][qp] = params->LambdaWeight[j] * pow (2, qp_temp/3.0);
+        SetLambda(j, qp, ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95));
+      }
+    }
+  }
+  else if (params->UseExplicitLambdaParams == 2) // consideration of fixed lambda values.
+  {
+    for (j = 0; j < 6; j++)
+    {
+      for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
+      {
+        qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
+
+        img->lambda_md[j][qp] = params->FixedLambda[j];
+        SetLambda(j, qp, ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95));
+      }
+    }
+  }
+  else
+  {
+    for (j = 0; j < 5; j++)
+    {
+      for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
+      {
+        qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
+
+        if (params->successive_Bframe > 0)
+          img->lambda_md[j][qp] = 0.68 * pow (2, qp_temp/3.0)
+          * (j == B_SLICE && img->b_frame_to_code != 0 ? dClip3(2.00, 4.00, (qp_temp / 6.0)) : (j == SP_SLICE) ? dClip3(1.4,3.0,(qp_temp / 12.0)) : 1.0);
         else
-        { 
-          img->lambda_md[j][qp] = QP2QUANT[imax(0,qp - SHIFT_QP)];
-        }
-        for (k = F_PEL; k <= Q_PEL; k++)
+          img->lambda_md[j][qp] = 0.85 * pow (2, qp_temp/3.0) * ((j == SP_SLICE) ? dClip3(1.4, 3.0,(qp_temp / 12.0)) : 1.0);
+
+        // Scale lambda due to hadamard qpel only consideration
+        img->lambda_md[j][qp] = ((params->MEErrorMetric[H_PEL] == ERROR_SATD && params->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
+        //img->lambda_md[j][qp] = (j == B_SLICE && params->BRefPictures == 2 && img->b_frame_to_code == 0 ? 0.50 : 1.00) * img->lambda_md[j][qp];
+
+        if (j == B_SLICE)
         {
-          img->lambda_me[j][qp][k]  = img->lambda_md[j][qp];
-          img->lambda_me[j][qp][k] *= params->MEErrorMetric[k] == ERROR_SSE ? img->lambda_me[j][qp][k] : 1;
-          img->lambda_mf[j][qp][k]  = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
+          img->lambda_md[5][qp] = img->lambda_md[j][qp];
+
+          if (img->b_frame_to_code != 0)
+          {
+            if (params->HierarchicalCoding == 2)
+              img->lambda_md[5][qp] *= (1.0 - dmin(0.4, 0.2 * (double) gop_structure[img->b_frame_to_code-1].hierarchy_layer));
+            else
+              img->lambda_md[5][qp] *= 0.80;
+
+          }
+          SetLambda(5, qp, lambda_scale);
         }
+        else
+          img->lambda_md[j][qp] *= lambda_scale;
+
+        SetLambda(j, qp, 1.0);
 
         if (params->CtxAdptLagrangeMult == 1)
         {
-          int lambda_qp = (qp >= 32 && !params->RCEnable) ? imax(0, qp-4) : imax(0, qp-6);
+          int lambda_qp = (qp >= 32 && !params->RCEnable) ? imax(0, qp - 4) : imax(0, qp - 6);
           img->lambda_mf_factor[j][qp] = log (img->lambda_me[j][lambda_qp][Q_PEL] + 1.0) / log (2.0);
         }
       }
     }
   }
+
+  UpdateMELambda(img);
 }
 
+
+void SetLagrangianMultipliersOff()
+{
+  int qp, j, k;
+  double qp_temp;
+
+  for (j = 0; j < 6; j++)
+  {
+    for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
+    {
+      qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
+
+      switch (params->UseExplicitLambdaParams)
+      {
+      case 1:  // explicit lambda weights
+        img->lambda_md[j][qp] = sqrt(params->LambdaWeight[j] * pow (2, qp_temp/3.0));
+        break;
+      case 2: // explicit lambda
+        img->lambda_md[j][qp] = sqrt(params->FixedLambda[j]);
+        break;
+      default:
+        img->lambda_md[j][qp] = QP2QUANT[imax(0,qp - SHIFT_QP)];
+        break;
+      }
+
+      for (k = F_PEL; k <= Q_PEL; k++)
+      {
+        img->lambda_me[j][qp][k]  = (params->MEErrorMetric[k] == ERROR_SSE) ? (img->lambda_md[j][qp] * img->lambda_md[j][qp]) : img->lambda_md[j][qp];
+        img->lambda_mf[j][qp][k]  = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
+      }
+
+      if (params->CtxAdptLagrangeMult == 1)
+      {
+        int lambda_qp = (qp >= 32 && !params->RCEnable) ? imax(0, qp-4) : imax(0, qp-6);
+        img->lambda_mf_factor[j][qp] = log (img->lambda_me[j][lambda_qp][Q_PEL] + 1.0) / log (2.0);
+      }
+    }
+  }
+  UpdateMELambda(img);
+}
diff --git a/lencod/src/transform8x8.c b/lencod/src/transform8x8.c
index b9640fb..a463007 100644
--- a/lencod/src/transform8x8.c
+++ b/lencod/src/transform8x8.c
@@ -39,137 +39,6 @@
 int   cofAC8x8_chroma[2][4][2][18];
 static int diff64[64];
 
-const int quant_coef8[6][8][8] =
-{
-  {
-    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {13107, 12222,  16777,  12222,  13107,  12222,  16777,  12222},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428},
-    {16777, 15481,  20972,  15481,  16777,  15481,  20972,  15481},
-    {12222, 11428,  15481,  11428,  12222,  11428,  15481,  11428}
-  },
-  {
-    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {11916, 11058,  14980,  11058,  11916,  11058,  14980,  11058},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826},
-    {14980, 14290,  19174,  14290,  14980,  14290,  19174,  14290},
-    {11058, 10826,  14290,  10826,  11058,  10826,  14290,  10826}
-  },
-  {
-    {10082, 9675,   12710,  9675,   10082,  9675, 12710,  9675},
-    {9675,  8943,   11985,  8943,   9675,   8943, 11985,  8943},
-    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
-    {9675,  8943,   11985,  8943,   9675,   8943, 11985,  8943},
-    {10082, 9675,   12710,  9675,   10082,  9675, 12710,  9675},
-    {9675,  8943,   11985,  8943,   9675, 8943, 11985,  8943},
-    {12710, 11985,  15978,  11985,  12710,  11985,  15978,  11985},
-    {9675,  8943,   11985,  8943,   9675, 8943, 11985,  8943}
-  },
-  {
-    { 9362,  8931, 11984,  8931,  9362,  8931, 11984,   8931},
-    { 8931,  8228, 11259,  8228,  8931,  8228, 11259,   8228},
-    {11984, 11259, 14913, 11259, 11984, 11259, 14913,  11259},
-    { 8931,  8228, 11259,  8228,  8931,  8228, 11259,   8228},
-    { 9362,  8931, 11984,  8931,  9362,  8931, 11984,   8931},
-    { 8931,  8228, 11259,  8228,  8931,  8228, 11259,   8228},
-    {11984, 11259, 14913, 11259, 11984, 11259, 14913,  11259},
-    { 8931,  8228, 11259,  8228,  8931,  8228, 11259,   8228}
-  },
-  {
-    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {8192,  7740, 10486,  7740, 8192, 7740, 10486,  7740},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346},
-    {10486, 9777, 13159,  9777, 10486,  9777, 13159,  9777},
-    {7740,  7346, 9777, 7346, 7740, 7346, 9777, 7346}
-  },
-  {
-    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {7282,  6830, 9118, 6830, 7282, 6830, 9118, 6830},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428},
-    {9118,  8640, 11570,  8640, 9118, 8640, 11570,  8640},
-    {6830,  6428, 8640, 6428, 6830, 6428, 8640, 6428}
-  }
-};
-
-
-const int dequant_coef8[6][8][8] =
-{
-  {
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {20,  19, 25, 19, 20, 19, 25, 19},
-    {19,  18, 24, 18, 19, 18, 24, 18},
-    {25,  24, 32, 24, 25, 24, 32, 24},
-    {19,  18, 24, 18, 19, 18, 24, 18}
-  },
-  {
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {22,  21, 28, 21, 22, 21, 28, 21},
-    {21,  19, 26, 19, 21, 19, 26, 19},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {21,  19, 26, 19, 21, 19, 26, 19}
-  },
-  {
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {26,  24, 33, 24, 26, 24, 33, 24},
-    {24,  23, 31, 23, 24, 23, 31, 23},
-    {33,  31, 42, 31, 33, 31, 42, 31},
-    {24,  23, 31, 23, 24, 23, 31, 23}
-  },
-  {
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {28,  26, 35, 26, 28, 26, 35, 26},
-    {26,  25, 33, 25, 26, 25, 33, 25},
-    {35,  33, 45, 33, 35, 33, 45, 33},
-    {26,  25, 33, 25, 26, 25, 33, 25}
-  },
-  {
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {32,  30, 40, 30, 32, 30, 40, 30},
-    {30,  28, 38, 28, 30, 28, 38, 28},
-    {40,  38, 51, 38, 40, 38, 51, 38},
-    {30,  28, 38, 28, 30, 28, 38, 28}
-  },
-  {
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {36,  34, 46, 34, 36, 34, 46, 34},
-    {34,  32, 43, 32, 34, 32, 43, 32},
-    {46,  43, 58, 43, 46, 43, 58, 43},
-    {34,  32, 43, 32, 34, 32, 43, 32}
-  }
-
-};
-
-
 //! single scan pattern
 //static const byte SNGL_SCAN8x8[64][2] = {
 const byte SNGL_SCAN8x8[64][2] = {
@@ -226,30 +95,37 @@ static int **fadjust8x8 = NULL;
 ************************************************************************
 */
 //For residual DPCM
-int Residual_DPCM_8x8(int ipmode, int m7[16][16], int block_y, int block_x)
+int Residual_DPCM_8x8(int ipmode, int ores[16][16], int rres[16][16],int block_y, int block_x)
 {
   int i,j;
   int temp[8][8];
 
   if(ipmode==VERT_PRED)
-  {    
+  { 
+
+    for (j=0; j<8; j++)
+     temp[0][j] = ores[block_y][block_x+j];
+
     for (i=1; i<8; i++) 
       for (j=0; j<8; j++)
-        temp[i][j] =  m7[block_y+i][block_x+j] - m7[block_y+i-1][block_x+j];
+        temp[i][j] =  ores[block_y+i][block_x+j] - ores[block_y+i-1][block_x+j];
 
-    for (i=1; i<8; i++)
-      for (j=0; j<8; j++)
-        m7[block_y+i][block_x+j] = temp[i][j];
+    for (i = 0; i < 8; i++)
+      for (j = 0; j < 8; j++)
+        rres[block_y+i][block_x+j] = temp[i][j];
   }
   else  //HOR_PRED
   {
     for (i=0; i<8; i++)
-      for (j=1; j<8; j++)
-        temp[i][j] = m7[block_y+i][block_x+j] - m7[block_y+i][block_x+j-1];
+     temp[i][0] = ores[block_y + i][block_x];
 
     for (i=0; i<8; i++)
       for (j=1; j<8; j++)
-        m7[block_y+i][block_x+j] = temp[i][j];
+        temp[i][j] = ores[block_y+i][block_x+j] - ores[block_y+i][block_x+j-1];
+
+    for (i=0; i<8; i++)
+      for (j=0; j<8; j++)
+        rres[block_y+i][block_x+j] = temp[i][j];
   }
   return 0;
 }
@@ -389,8 +265,8 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_Low (Macroblock *currMB, int b8, dou
   imgpel    *img_org, *img_prd;
   int       *residual;
   int left_available, up_available, all_available;
-  int    (*curr_res)[16] = img->m7[0]; 
-  imgpel (*curr_mpr)[16] = img->mpr[0];
+  int    (*mb_ores)[16] = img->mb_ores[0]; 
+  imgpel (*mb_pred)[16] = img->mb_pred[0];
   int *mb_size = img->mb_size[IS_LUMA];
 
   char   upMode;
@@ -478,8 +354,8 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_Low (Macroblock *currMB, int b8, dou
       {
         for (i=0; i<8; i++)
         {
-          img->mpr[k][block_y+j][block_x+i]  = img->mpr_8x8[k][best_ipmode][j][i]; 
-          img->m7[k][block_y+j][block_x+i]   = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][best_ipmode][j][i];
+          img->mb_pred[k][block_y+j][block_x+i]  = img->mpr_8x8[k][best_ipmode][j][i]; 
+          img->mb_ores[k][block_y+j][block_x+i]   = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][best_ipmode][j][i];
         }
       }
       ipmode_DPCM=best_ipmode; 
@@ -500,10 +376,10 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_Low (Macroblock *currMB, int b8, dou
   // get prediction and prediction error
   for (j = block_y; j < block_y + 8; j++)
   {
-    memcpy(&curr_mpr[j][block_x],img->mpr_8x8[0][best_ipmode][j - block_y], 8 * sizeof(imgpel));
+    memcpy(&mb_pred[j][block_x],img->mpr_8x8[0][best_ipmode][j - block_y], 8 * sizeof(imgpel));
     img_org  = &pCurImg[img->opix_y+j][pic_opix_x];
-    img_prd  = &curr_mpr[j][block_x];
-    residual = &curr_res[j][block_x];
+    img_prd  = &mb_pred[j][block_x];
+    residual = &mb_ores[j][block_x];
     for (i=0; i<8; i++)
     {
       *residual++ = *img_org++ - *img_prd++;
@@ -545,8 +421,8 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
   extern  int ****cofAC8x8CbCr[2];
   int uv, c_nzCbCr[3];
   int left_available, up_available, all_available;
-  int    (*curr_res)[16] = img->m7[0]; 
-  imgpel (*curr_mpr)[16] = img->mpr[0];
+  int    (*mb_ores)[16] = img->mb_ores[0]; 
+  imgpel (*mb_pred)[16] = img->mb_pred[0];
   int *mb_size = img->mb_size[IS_LUMA];
 
   char   upMode;
@@ -603,10 +479,10 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
       // get prediction and prediction error
       for (j=block_y; j < block_y  + 8; j++)
       {
-        memcpy(&curr_mpr[j][block_x],img->mpr_8x8[0][ipmode][j - block_y], 8 * sizeof(imgpel));
+        memcpy(&mb_pred[j][block_x],img->mpr_8x8[0][ipmode][j - block_y], 8 * sizeof(imgpel));
         img_org  = &pCurImg[img->opix_y+j][pic_opix_x];
-        img_prd  = &curr_mpr[j][block_x];
-        residual = &curr_res[j][block_x];
+        img_prd  = &mb_pred[j][block_x];
+        residual = &mb_ores[j][block_x];
         for (i=0; i<8; i++)
         {
           *residual++ = *img_org++ - *img_prd++;
@@ -618,10 +494,11 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
         {
           for (j=0; j<8; j++)
           {
-            memcpy(&img->mpr[k][block_y+j][block_x],img->mpr_8x8[k][ipmode][j], 8 * sizeof(imgpel));
+            memcpy(&img->mb_pred[k][block_y+j][block_x],img->mpr_8x8[k][ipmode][j], 8 * sizeof(imgpel));
             for (i=0; i<8; i++)
             {
-              img->m7[k][block_y+j][block_x+i] = (int) (pImgOrg[k][pic_opix_y+j][pic_opix_x+i] - img->mpr_8x8[k][ipmode][j][i]);
+              img->mb_ores[k][block_y+j][block_x+i] = (int) (pImgOrg[k][pic_opix_y+j][pic_opix_x+i] - img->mpr_8x8[k][ipmode][j][i]);
+              img->mb_ores[k][block_y+j][block_x+i] = img->mb_ores[k][block_y+j][block_x+i]; // line is temporary until we fix code to use img->mb_ores
             }
           }
         }
@@ -703,8 +580,8 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
       {
         for (i=0; i<8; i++)
         {
-          img->mpr[k][block_y+j][block_x+i]  = img->mpr_8x8[k][best_ipmode][j][i]; 
-          img->m7[k][block_y+j][block_x+i]   = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][best_ipmode][j][i];
+          img->mb_pred[k][block_y+j][block_x+i] = img->mpr_8x8[k][best_ipmode][j][i]; 
+          img->mb_ores[k][block_y+j][block_x+i] = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][best_ipmode][j][i];
         }
       }
       ipmode_DPCM = best_ipmode; 
@@ -744,7 +621,7 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
   for (y=0; y<8; y++)
   {
     memcpy(&enc_picture->imgY[pic_pix_y + y][pic_pix_x], rec8x8[0][y], 8 * sizeof(imgpel));
-    memcpy(&curr_mpr[block_y + y][block_x], img->mpr_8x8[0][best_ipmode][y], 8 * sizeof(imgpel));
+    memcpy(&mb_pred[block_y + y][block_x], img->mpr_8x8[0][best_ipmode][y], 8 * sizeof(imgpel));
   }
   if (img->P444_joined)
   {
@@ -757,8 +634,8 @@ int Mode_Decision_for_new_8x8IntraBlocks_JM_High (Macroblock *currMB, int b8, do
     {
       memcpy(&enc_picture->imgUV[0][pic_pix_y+y][pic_pix_x], rec8x8[1][y], 8 * sizeof(imgpel));
       memcpy(&enc_picture->imgUV[1][pic_pix_y+y][pic_pix_x], rec8x8[2][y], 8 * sizeof(imgpel));
-      memcpy(&img->mpr[1][block_y+y][block_x], img->mpr_8x8[1][best_ipmode][y], 8 * sizeof(imgpel));
-      memcpy(&img->mpr[2][block_y+y][block_x], img->mpr_8x8[2][best_ipmode][y], 8 * sizeof(imgpel));
+      memcpy(&img->mb_pred[1][block_y+y][block_x], img->mpr_8x8[1][best_ipmode][y], 8 * sizeof(imgpel));
+      memcpy(&img->mb_pred[2][block_y+y][block_x], img->mpr_8x8[2][best_ipmode][y], 8 * sizeof(imgpel));
     }
   }
 
@@ -1542,7 +1419,7 @@ double RDCost_for_8x8IntraBlocks(Macroblock *currMB, int *nonzero, int b8, int i
   if(img->P444_joined) 
   {
     ColorPlane k;
-    ipmode_DPCM = NO_INTRA_PMODE;  //For residual DPCM
+
     for (k = PLANE_U; k <= PLANE_V; k++)
     {
       select_plane(k);
@@ -1550,13 +1427,14 @@ double RDCost_for_8x8IntraBlocks(Macroblock *currMB, int *nonzero, int b8, int i
       {
       for (i=0; i<8; i++)
       {         
-      img->mpr[k][block_y+j][block_x+i]  = img->mpr_8x8[k][ipmode][j][i];
-      img->m7[k][j][i] = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][ipmode][j][i];
+      img->mb_pred[k][block_y+j][block_x+i]  = img->mpr_8x8[k][ipmode][j][i];
+      img->mb_ores[k][j][i] = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][ipmode][j][i];
       }
       }*/
       c_nzCbCr[k ]= pDCT_8x8(currMB, k, b8, &dummy,1);
       distortion += compute_SSE(&pImgOrg[k][pic_opix_y], &enc_picture->p_curr_img[pic_pix_y], pic_pix_x, pic_pix_x, 8, 8);
     }
+	  ipmode_DPCM = NO_INTRA_PMODE;
     select_plane(PLANE_Y);
   }
   else if( img->yuv_format==YUV444 && IS_INDEPENDENT(params) )  //For residual DPCM
@@ -1646,8 +1524,9 @@ int dct_8x8(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intr
   int*  ACLevel = img->cofAC[pl_off][0][0];
   int*  ACRun   = img->cofAC[pl_off][0][1];  
   imgpel **img_enc       = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl];   
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];
 
   int max_imgpel_value   = img->max_imgpel_value;
   int qp = currMB->qp_scaled[pl];
@@ -1662,25 +1541,25 @@ int dct_8x8(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intr
   fadjust8x8 = img->AdaptiveRounding ? (pl ? &img->fadjust8x8Cr[pl-1][intra][block_y] : &img->fadjust8x8[intra][block_y]) :NULL;
 
   // Forward 8x8 transform
-  forward8x8(curr_res, curr_res, block_y, block_x);
+  forward8x8(mb_ores, mb_rres, block_y, block_x);
 
   // Quantization process
-  nonzero = quant_8x8(&curr_res[block_y], block_y, block_x, qp, ACLevel, ACRun, fadjust8x8, 
+  nonzero = quant_8x8(&mb_rres[block_y], block_y, block_x, qp, ACLevel, ACRun, fadjust8x8, 
     levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST8x8[params->disthres]);
 
   if (nonzero)
   {
     // Inverse 8x8 transform
-    inverse8x8(curr_res, curr_res, block_y, block_x);
+    inverse8x8(mb_rres, mb_rres, block_y, block_x);
 
     // generate final block
-    SampleReconstruct (img_enc, curr_mpr, curr_res, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
+    SampleReconstruct (img_enc, mb_pred, mb_rres, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
   }
   else // if (nonzero) => No transformed residual. Just use prediction.
   {      
     for( j=block_y; j< block_y + BLOCK_SIZE_8x8; j++)
     {
-      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(curr_mpr[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
+      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
     }
   }  
 
@@ -1711,9 +1590,10 @@ int dct_8x8_cavlc(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, in
   int block_x = 8*(b8 & 0x01);
   int block_y = 8*(b8 >> 1);
   int pl_off = b8+ (pl<<2);
-  imgpel **img_enc       = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[MB_BLOCK_SIZE] = img->mpr[pl];
-  int    (*curr_res)[MB_BLOCK_SIZE] = img->m7[pl];   
+  imgpel **img_enc = enc_picture->p_curr_img;
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];  
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];   
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];   
 
   int max_imgpel_value   = img->max_imgpel_value;
 
@@ -1729,25 +1609,25 @@ int dct_8x8_cavlc(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, in
   fadjust8x8 = img->AdaptiveRounding ? (pl ? &img->fadjust8x8Cr[pl-1][intra][block_y] : &img->fadjust8x8[intra][block_y]) :NULL;
 
   // Forward 8x8 transform
-  forward8x8(curr_res, curr_res, block_y, block_x);
+  forward8x8(mb_ores, mb_rres, block_y, block_x);
 
   // Quantization process
-  nonzero = quant_8x8cavlc_around(&curr_res[block_y], block_y, block_x, qp, img->cofAC[pl_off], fadjust8x8, 
+  nonzero = quant_8x8cavlc(&mb_rres[block_y], block_y, block_x, qp, img->cofAC[pl_off], fadjust8x8, 
     levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST8x8[params->disthres]);
 
   if (nonzero)
   {
     // Inverse 8x8 transform
-    inverse8x8(curr_res, curr_res, block_y, block_x);
+    inverse8x8(mb_rres, mb_rres, block_y, block_x);
 
     // generate final block
-    SampleReconstruct (img_enc, curr_mpr, curr_res, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
+    SampleReconstruct (img_enc, mb_pred, mb_rres, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
   }
   else // if (nonzero) => No transformed residual. Just use prediction.
   {      
     for( j=block_y; j< block_y + BLOCK_SIZE_8x8; j++)
     {
-      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(curr_mpr[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
+      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
     }
   }  
 
@@ -1767,8 +1647,9 @@ int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int i
   int*  ACLevel = img->cofAC[pl_off][0][0];
   int*  ACRun   = img->cofAC[pl_off][0][1];  
   imgpel **img_enc       = enc_picture->p_curr_img;
-  imgpel (*curr_mpr)[16] = img->mpr[pl];
-  int    (*curr_res)[16] = img->m7[pl];   
+  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
+  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
+  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];
 
   int scan_poss[4] = { 0 }, runs[4] = { -1, -1, -1, -1 };
   int MCcoeff = 0;
@@ -1781,9 +1662,9 @@ int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int i
   runs[0]=runs[1]=runs[2]=runs[3]=-1;
   scan_poss[0] = scan_poss[1] = scan_poss[2] = scan_poss[3] = 0;
 
-  if((ipmode_DPCM<2))
+  if( (ipmode_DPCM < 2)&&(intra))
   {
-    Residual_DPCM_8x8(ipmode_DPCM, curr_res, block_y, block_x);
+    Residual_DPCM_8x8(ipmode_DPCM, mb_ores, mb_rres, block_y, block_x);
   }
 
   for (coeff_ctr=0; coeff_ctr < 64; coeff_ctr++)
@@ -1799,7 +1680,7 @@ int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int i
       runs[MCcoeff]++;
     }
 
-    m7 = &curr_res[block_y + j][block_x + i];
+    m7 = &mb_rres[block_y + j][block_x + i];
 
     if (img->AdaptiveRounding)
     {
@@ -1838,17 +1719,17 @@ int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int i
       img->cofAC[pl_off][i][0][scan_poss[i]] = 0;
   }
 
-  if(ipmode_DPCM<2)  //For residual DPCM
+  if( (ipmode_DPCM < 2) && (intra))
   {
-    Inv_Residual_DPCM_8x8(curr_res, block_y, block_x);
+    Inv_Residual_DPCM_8x8(mb_rres, block_y, block_x);
   }
 
   for( j=block_y; j<block_y + BLOCK_SIZE_8x8; j++)
   {            
     for( i=block_x; i< block_x + BLOCK_SIZE_8x8; i++)
     {
-      curr_res[j][i] += curr_mpr[j][i];
-      img_enc[img->pix_y + j][img->pix_x + i]= (imgpel) curr_res[j][i];
+      mb_rres[j][i] += mb_pred[j][i];
+      img_enc[img->pix_y + j][img->pix_x + i]= (imgpel) mb_rres[j][i];
     }
   }  
 
@@ -1857,6 +1738,14 @@ int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int i
 }
 
 
+/*static inline void compute_diff(int *diff, imgpel *cimg, imgpel *cmpr, int width)
+{
+  int i;
+  for (i = 0; i < width; i++)
+  {
+    *(diff++) = *(cimg++) - *(cmpr++);
+  }
+}*/
 /*!
 *************************************************************************************
 * \brief
@@ -1871,12 +1760,15 @@ void compute_comp_cost8x8(imgpel **cur_img, imgpel mpr8x8[16][16], int pic_opix_
 
   for (j=0; j<8; j++)
   {
+  //  compute_diff(diff, &cur_img[j][pic_opix_x], &mpr8x8[j][0], BLOCK_SIZE_8x8);
+
     cimg = &cur_img[j][pic_opix_x];
     cmpr = &mpr8x8[j][0];
     for (i=0; i<8; i++)
     {
       *diff++ = *cimg++ - *cmpr++;
     }
+
   }
   *cost += distortion8x8 (diff64);
 }
diff --git a/lencod/src/vlc.c b/lencod/src/vlc.c
index 110bf43..02aa4ca 100644
--- a/lencod/src/vlc.c
+++ b/lencod/src/vlc.c
@@ -19,6 +19,7 @@
 #include <math.h>
 
 #include "global.h"
+#include "enc_statistics.h"
 #include "vlc.h"
 
 #if TRACE
@@ -750,7 +751,6 @@ int symbol2vlc(SyntaxElement *sym)
  */
 int writeSyntaxElement_VLC(SyntaxElement *se, DataPartition *dp)
 {
-
   se->inf = se->value1;
   se->len = se->value2;
   symbol2vlc(se);
@@ -1331,15 +1331,15 @@ int writeSyntaxElement_Level_VLCN(SyntaxElement *se, int vlc, DataPartition *dp,
 }
 
 
+#if TRACE
+int bitcounter = 0;
+
 /*!
  ************************************************************************
  * \brief
  *    Write out a trace string on the trace file
  ************************************************************************
  */
-#if TRACE
-int bitcounter = 0;
-
 void trace2out(SyntaxElement *sym)
 {
   static
@@ -1415,9 +1415,9 @@ void writeVlcByteAlign(Bitstream* currStream)
 {
   if (currStream->bits_to_go < 8)
   { // trailing bits to process
-    currStream->byte_buf = (currStream->byte_buf <<currStream->bits_to_go) | (0xff >> (8 - currStream->bits_to_go));
-    stats->bit_use_stuffingBits[img->type]+=currStream->bits_to_go;
-    currStream->streamBuffer[currStream->byte_pos++]=currStream->byte_buf;
+    currStream->byte_buf = (currStream->byte_buf << currStream->bits_to_go) | (0xff >> (8 - currStream->bits_to_go));
+    stats->bit_use_stuffingBits[img->type] += currStream->bits_to_go;
+    currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf;
     currStream->bits_to_go = 8;
   }
 }
diff --git a/lencod/src/weighted_prediction.c b/lencod/src/weighted_prediction.c
index 6547911..99251bb 100644
--- a/lencod/src/weighted_prediction.c
+++ b/lencod/src/weighted_prediction.c
@@ -4,7 +4,7 @@
 * \file weighted_prediction.c
 *
 * \brief
-*    Estimate weights for WP
+*    Estimate weights for WP using DC method
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
@@ -26,12 +26,21 @@
 */
 void InitWP(InputParameters *params)
 {
-  //if (params->WPMethod == 0)
+  switch ( params->WPMethod )
   {
-    EstimateWPPSlice = estimate_weighting_factor_P_slice;
-    EstimateWPBSlice = estimate_weighting_factor_B_slice;
-    TestWPPSlice = test_wp_P_slice;
-    TestWPBSlice = test_wp_B_slice;
+  default:
+  case 0:
+    EstimateWPPSlice = EstimateWPPSliceAlg0;
+    EstimateWPBSlice = EstimateWPBSliceAlg0;
+    TestWPPSlice = TestWPPSliceAlg0;
+    TestWPBSlice = TestWPBSliceAlg0;
+    break;
+  case 1:
+    EstimateWPPSlice = EstimateWPPSliceAlg1;
+    EstimateWPBSlice = EstimateWPBSliceAlg1;
+    TestWPPSlice = TestWPPSliceAlg1;
+    TestWPBSlice = TestWPBSliceAlg1;
+    break;
   }
 }
 
@@ -45,6 +54,7 @@ double ComputeImgSum(imgpel **CurrentImage, int height, int width)
 {
   int i, j;
   double sum_value = 0.0;
+
   for (i = 0; i < height; i++)
   {
     for (j = 0; j < width; j++)
@@ -62,17 +72,15 @@ double ComputeImgSum(imgpel **CurrentImage, int height, int width)
 ************************************************************************
 */
 
-void estimate_weighting_factor_P_slice(int select_offset)
+void EstimateWPPSliceAlg0(ImageParameters *img, InputParameters *params, int select_offset)
 {
-  int i, j, n;
-
-  int index;
-  int comp;
   double dc_org = 0.0;
+  double dc_org_UV[2] = {0.0};
   double dc_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double dc_ref_UV[MAX_REFERENCE_PICTURES][2] = { {0.0}};
 
+  int i, n, k;
   int default_weight[3];
-
   int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
   int weight[2][MAX_REFERENCE_PICTURES][3];
   int offset[2][MAX_REFERENCE_PICTURES][3];
@@ -80,71 +88,109 @@ void estimate_weighting_factor_P_slice(int select_offset)
 
   imgpel **tmpPtr;
 
-  luma_log_weight_denom = 5;
+  luma_log_weight_denom   = 5;
   chroma_log_weight_denom = 5;
-  wp_luma_round = 1 << (luma_log_weight_denom - 1);
-  wp_chroma_round = 1 << (chroma_log_weight_denom - 1);
-  default_weight[0] = 1 << luma_log_weight_denom;
-  default_weight[1] = default_weight[2] = 1 << chroma_log_weight_denom;
 
-  /* set all values to defaults */
-  for (i = 0; i < 2 + list_offset; i++)
+  wp_luma_round           = 1 << (luma_log_weight_denom - 1);
+  wp_chroma_round         = 1 << (chroma_log_weight_denom - 1);
+  default_weight[0]       = 1 << luma_log_weight_denom;
+  default_weight[1]       = default_weight[2] = 1 << chroma_log_weight_denom;
+  
+  dc_org = ComputeImgSum(pCurImg, img->height, img->width);
+
+  if (params->ChromaWeightSupport == 1)
   {
-    for (j = 0; j < listXsize[i]; j++)
+    for (k = 0; k < 2; k++)
     {
-      for (n = 0; n < 3; n++)
-      {
-        weight[i][j][n] = default_weight[n];
-        wp_weight[i][j][n] = default_weight[n];
-        wp_offset[i][j][n] = 0;
-        offset[i][j][n] = 0;
-      }
-    }
+      dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+    } 
   }
 
-  dc_org = ComputeImgSum(pCurImg, img->height, img->width);
-  
   for (clist = 0; clist < 2 + list_offset; clist++)
   {
     for (n = 0; n < listXsize[clist]; n++)
     {
-      // Y
-      tmpPtr = listX[clist][n]->p_curr_img;      
-      dc_ref[n] = ComputeImgSum(tmpPtr, img->height, img->width);
-
-      if (select_offset == 0)
+      if ( wpxDetermineWP( params, img, clist, n ) )
       {
-        if (dc_ref[n] != 0.0)
-          weight[clist][n][0] = (int) (default_weight[0] * dc_org / dc_ref[n] + 0.5);
+        /* set all values to defaults */
+        for (i = 0; i < 3; i++)
+        {
+          weight[clist][n][i]    = default_weight[i];
+          wp_weight[clist][n][i] = default_weight[i];
+          wp_offset[clist][n][i] = 0;
+          offset[clist][n][i]    = 0;
+        }
+
+        // Y
+        tmpPtr = listX[clist][n]->p_curr_img;      
+        dc_ref[n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+        if (params->ChromaWeightSupport == 1)
+        {
+          for (k = 0; k < 2; k++)
+          {
+            // UV
+            tmpPtr = listX[clist][n]->imgUV[k];
+            dc_ref_UV[n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+          }        
+        }
+
+        if (select_offset == 0)
+        {
+          if (dc_ref[n] != 0.0)
+            weight[clist][n][0] = (int) (default_weight[0] * dc_org / dc_ref[n] + 0.5);
+          else
+            weight[clist][n][0] = default_weight[0];  // only used when reference picture is black
+          weight[clist][n][0] = iClip3(-128, 127, weight[clist][n][0]);
+          if (params->ChromaWeightSupport == 1)
+          {
+            if (dc_ref_UV[n][0] != 0)
+              weight[clist][n][1] = (int) (default_weight[1] * dc_org_UV[0] / dc_ref_UV[n][0] + 0.5);
+            else
+              weight[clist][n][1] = default_weight[1];  // only used when reference picture is black
+            weight[clist][n][1] = iClip3(-128, 127, weight[clist][n][1]);
+
+            if (dc_ref_UV[n][1] != 0)
+              weight[clist][n][2] = (int) (default_weight[2] * dc_org_UV[1] / dc_ref_UV[n][1] + 0.5);
+            else
+              weight[clist][n][2] = default_weight[2];  // only used when reference picture is black
+            weight[clist][n][2] = iClip3(-64, 128, weight[clist][n][2]);
+          }
+        }
         else
-          weight[clist][n][0] = default_weight[0];  // only used when reference picture is black
-        weight[clist][n][0] = iClip3(-128, 127, weight[clist][n][0]);
-      }
-      else
-      {
-        offset[clist][n][0] = (int) ((dc_org - dc_ref[n])/(img->size)+0.5);
-        offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
-        offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
-        offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
-        weight[clist][n][0] = default_weight[0];
-      }
+        {
+          offset[clist][n][0] = (int) ((dc_org - dc_ref[n])/(img->size)+0.5);
+          offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+          offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
+          offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
+          weight[clist][n][0] = default_weight[0];
 
-      weight[clist][n][1] = default_weight[1];
-      weight[clist][n][2] = default_weight[2];
-      offset[clist][n][1] = 0;
-      offset[clist][n][2] = 0;
-    }
-  }
+          if (params->ChromaWeightSupport == 1)
+          {
+            offset[clist][n][1] = (int) ((dc_org_UV[0] - dc_ref_UV[n][0])/(img->size_cr)+0.5);
+            offset[clist][n][1] = (offset[clist][n][1] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][1] = iClip3( -128, 127, offset[clist][n][1]);
+            offset[clist][n][1] = offset[clist][n][1]<<(img->bitdepth_chroma - 8);
+            
+            weight[clist][n][1] = default_weight[1];
+
+            offset[clist][n][2] = (int) ((dc_org_UV[1] - dc_ref_UV[n][1])/(img->size_cr)+0.5);
+            offset[clist][n][2] = (offset[clist][n][2] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][2] = iClip3( -128, 127, offset[clist][n][2]);
+            offset[clist][n][2] = offset[clist][n][2]<<(img->bitdepth_chroma - 8);
+
+            weight[clist][n][2] = default_weight[2];
+          }
+        }
 
-  for (clist=0; clist<2 + list_offset; clist++)
-  {
-    for (index = 0; index < listXsize[clist]; index++)
-    {
-      for (comp=0; comp < 3; comp ++)
-      {
-        wp_weight[clist][index][comp] = weight[clist][index][comp];
-        wp_offset[clist][index][comp] = offset[clist][index][comp];
-        // printf("index %d component %d weight %d offset %d\n",index,comp,weight[0][index][comp],offset[0][index][comp]);
+        for (i=0; i < 3; i ++)
+        {
+          wp_weight[clist][n][i] = weight[clist][n][i];
+          wp_offset[clist][n][i] = offset[clist][n][i];
+#if DEBUG_WP
+          printf("index %d component %d weight %d offset %d\n",n,i,weight[0][n][i],offset[0][n][i]);
+#endif
+        }
       }
     }
   }
@@ -153,41 +199,38 @@ void estimate_weighting_factor_P_slice(int select_offset)
 /*!
 ************************************************************************
 * \brief
-*    Estimates reference picture weighting factors
+*    Estimates reference picture weighting factors for B slices
 ************************************************************************
 */
-void estimate_weighting_factor_B_slice()
+void EstimateWPBSliceAlg0(ImageParameters *img, InputParameters *params)
 {
-  int i, j, n;
+  int i, j, k, n;
 
   int tx,DistScaleFactor;
 
   int index;
   int comp;
   double dc_org = 0.0;
+  double dc_org_UV[2] = { 0.0 };
   double dc_ref[6][MAX_REFERENCE_PICTURES] = { {0.0} };
-
-  int log_weight_denom;
+  double dc_ref_UV[6][MAX_REFERENCE_PICTURES][2] = { {{0.0}} };
 
   int default_weight[3];
   int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
   int weight[6][MAX_REFERENCE_PICTURES][3];
   int offset[6][MAX_REFERENCE_PICTURES][3];
   int im_weight[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
-  int im_offset[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
   int clist;
   int wf_weight, wf_offset;
   imgpel **tmpPtr;
 
-  if (active_pps->weighted_bipred_idc == 2) //! implicit mode
+  if (active_pps->weighted_bipred_idc == 2) //! implicit mode. Values are fixed and it is important to show it here
   {
     luma_log_weight_denom = 5;
     chroma_log_weight_denom = 5;
   }
-  else
+  else                                     //! explicit mode. Values can be changed for higher precision.
   {
-    //luma_log_weight_denom = 6;
-    //chroma_log_weight_denom = 6;
     luma_log_weight_denom = 5;
     chroma_log_weight_denom = 5;
   }
@@ -198,69 +241,51 @@ void estimate_weighting_factor_B_slice()
   default_weight[1] = 1 << chroma_log_weight_denom;
   default_weight[2] = 1 << chroma_log_weight_denom;
 
-  /* set all values to defaults */
-  for (i = 0; i < 2 + list_offset; i++)
-  {
-    for (j = 0; j < listXsize[i]; j++)
-    {
-      for (n = 0; n < 3; n++)
-      {
-        wp_weight[i][j][n] = default_weight[n];
-        wp_offset[i][j][n] = 0;
-        offset   [i][j][n] = 0;
-        weight   [i][j][n] = default_weight[n];
-      }
-    }
-  }
-
-  for (i = 0; i < listXsize[LIST_0]; i++)
+  if (active_pps->weighted_bipred_idc == 2) //! implicit mode
   {
-    for (j = 0; j < listXsize[LIST_1]; j++)
+    for (i = 0; i < listXsize[LIST_0]; i++)
     {
-      int td, tb;
-      td = iClip3(-128, 127,(listX[LIST_1][j]->poc - listX[LIST_0][i]->poc));
-      tb = iClip3(-128, 127,(enc_picture->poc - listX[LIST_0][i]->poc));
-      for (comp = 0; comp < 3; comp++)
+      for (j = 0; j < listXsize[LIST_1]; j++)
       {
-        // implicit weights
-        if (td == 0)
-        {
-          im_weight[1][i][j][comp] = default_weight[comp];
-          im_weight[0][i][j][comp] = default_weight[comp];
-          im_offset[1][i][j][comp] = 0;
-          im_offset[0][i][j][comp] = 0;
-        }
-        else
+        int td, tb;
+        td = iClip3(-128, 127,(listX[LIST_1][j]->poc - listX[LIST_0][i]->poc));
+        tb = iClip3(-128, 127,(enc_picture->poc - listX[LIST_0][i]->poc));
+        for (comp = 0; comp < 3; comp++)
         {
-          tx = (16384 + iabs(td/2))/td;
-          DistScaleFactor = iClip3(-1024, 1023, (tx*tb + 32 )>>6);
-          im_weight[1][i][j][comp] = DistScaleFactor>>2;
-          if (im_weight[1][i][j][comp] < -64 || im_weight[1][i][j][comp] >128)
+          // implicit weights
+          if (td == 0)
+          {
+            im_weight[0][i][j][comp] = default_weight[comp];
             im_weight[1][i][j][comp] = default_weight[comp];
-          im_weight[0][i][j][comp] = 64 - im_weight[1][i][j][comp];
-          im_offset[1][i][j][comp] = 0;
-          im_offset[0][i][j][comp] = 0;
+          }
+          else
+          {
+            tx = (16384 + iabs(td/2))/td;
+            DistScaleFactor = iClip3(-1024, 1023, (tx*tb + 32 )>>6);
+            im_weight[1][i][j][comp] = DistScaleFactor>>2;
+            if (im_weight[1][i][j][comp] < -64 || im_weight[1][i][j][comp] >128)
+              im_weight[1][i][j][comp] = default_weight[comp];
+            im_weight[0][i][j][comp] = 64 - im_weight[1][i][j][comp];
+          }
         }
+#if DEBUG_WP
+        printf ("%d imp weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n",enc_picture->poc, i, j,  im_weight[0][i][j][0], im_weight[1][i][j][0],
+          enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
+          DistScaleFactor ,tx,td,tb);
+#endif
       }
-      /*
-      printf ("%d imp weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n",enc_picture->poc, i, j,  im_weight[0][i][j][0], im_weight[1][i][j][0],
-      enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
-      DistScaleFactor ,tx,td,tb);
-      */
     }
-  }
 
-  if (active_pps->weighted_bipred_idc == 2) //! implicit mode
-  {
-    for (i = 0; i < listXsize[LIST_0]; i++)
+    for (k = 0; k < 2; k++)
     {
-      for (j = 0; j < listXsize[LIST_1]; j++)
+      for (i = 0; i < listXsize[LIST_0]; i++)
       {
-        for (comp = 0; comp < 3; comp++)
+        for (j = 0; j < listXsize[LIST_1]; j++)
         {
-          log_weight_denom = (comp == 0) ? luma_log_weight_denom : chroma_log_weight_denom;
-          wbp_weight[1][i][j][comp] = im_weight[1][i][j][comp] ;
-          wbp_weight[0][i][j][comp] = im_weight[0][i][j][comp];
+          for (comp = 0; comp < 3; comp++)
+          {
+            wbp_weight[k][i][j][comp] = im_weight[k][i][j][comp];
+          }
         }
       }
     }
@@ -269,12 +294,11 @@ void estimate_weighting_factor_B_slice()
     {
       for (index = 0; index < listXsize[clist]; index++)
       {
-        wp_weight[clist][index][0] = default_weight[0];
-        wp_weight[clist][index][1] = default_weight[1];
-        wp_weight[clist][index][2] = default_weight[2];
-        wp_offset[clist][index][0] = 0;
-        wp_offset[clist][index][1] = 0;
-        wp_offset[clist][index][2] = 0;
+        for (comp = 0; comp < 3; comp++)
+        {
+          wp_weight[clist][index][comp] = default_weight[comp];
+          wp_offset[clist][index][comp] = 0;
+        }
       }
     }
   }
@@ -282,51 +306,86 @@ void estimate_weighting_factor_B_slice()
   {
     dc_org = ComputeImgSum(pCurImg, img->height, img->width);
 
-    for (clist=0; clist<2 + list_offset; clist++)
+    if (params->ChromaWeightSupport == 1)
     {
-      for (n = 0; n < listXsize[clist]; n++)
+      for (k = 0; k < 2; k++)
       {
-        // To simplify these computations we may wish to perform these after a reference is 
-        // stored in the reference buffer and attach them to the storedimage structure!!!
-        // Y
-        tmpPtr = listX[clist][n]->p_curr_img;
-        dc_ref[clist][n] = ComputeImgSum(tmpPtr, img->height, img->width);
-
-        if (dc_ref[clist][n] != 0.0)
-          wf_weight = (int) (default_weight[0] * dc_org / dc_ref[clist][n] + 0.5);
-        else
-          wf_weight = default_weight[0];  // only used when reference picture is black
-        wf_weight = iClip3(-128, 127, wf_weight);
-        wf_offset = 0;
-
-        //    printf("dc_org = %d, dc_ref = %d, weight[%d] = %d\n",dc_org, dc_ref[n],n,weight[n][0]);
-
-        weight[clist][n][0] = wf_weight;
-        offset[clist][n][0] = wf_offset;
-
-        weight[clist][n][1] = default_weight[1];
-        weight[clist][n][2] = default_weight[2];        
-        offset[clist][n][1] = 0;
-        offset[clist][n][2] = 0;
-      }
+        dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+      } 
     }
 
-    if (active_pps->weighted_bipred_idc == 1)
+    for (clist=0; clist<2 + list_offset; clist++)
     {
-      for (clist=0; clist<2 + list_offset; clist++)
+      for (n = 0; n < listXsize[clist]; n++)
       {
-        for (index = 0; index < listXsize[clist]; index++)
+        if ( wpxDetermineWP( params, img, clist, n ) )
         {
-          for (comp = 0; comp < 3; comp++)
+          /* set all values to defaults */
+          for (i = 0; i < 3; i++)
+          {
+            wp_weight[clist][n][i] = default_weight[i];
+            wp_offset[clist][n][i] = 0;
+            offset   [clist][n][i] = 0;
+            weight   [clist][n][i] = default_weight[i];
+          }
+          // To simplify these computations we may wish to perform these after a reference is 
+          // stored in the reference buffer and attach them to the storedimage structure!!!
+          // Y
+          tmpPtr = listX[clist][n]->p_curr_img;
+          dc_ref[clist][n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+          if (dc_ref[clist][n] != 0.0)
+            wf_weight = (int) (default_weight[0] * dc_org / dc_ref[clist][n] + 0.5);
+          else
+            wf_weight = default_weight[0];  // only used when reference picture is black
+          wf_weight = iClip3(-128, 127, wf_weight);
+          wf_offset = 0;
+
+          //    printf("dc_org = %d, dc_ref = %d, weight[%d] = %d\n",dc_org, dc_ref[n],n,weight[n][0]);
+
+          weight[clist][n][0] = wf_weight;
+          offset[clist][n][0] = wf_offset;
+
+          // UV
+          if (params->ChromaWeightSupport == 1)
+          {          
+            for (k = 0; k < 2; k++)
+            {        	
+              tmpPtr = listX[clist][n]->imgUV[k];
+              dc_ref_UV[clist][n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+
+              if (dc_ref_UV[clist][n][k] != 0.0)
+                wf_weight = (int) (default_weight[k + 1] * dc_org_UV[k] / dc_ref_UV[clist][n][k] + 0.5);
+              else
+                wf_weight = default_weight[k + 1];  // only used when reference picture is black
+              wf_weight = iClip3(-128, 127, wf_weight);
+              wf_offset = 0;
+
+              weight[clist][n][k + 1] = wf_weight;
+              offset[clist][n][k + 1] = wf_offset;
+            }
+          }
+          else
           {
-            wp_weight[clist][index][comp] = weight[clist][index][comp];
-            wp_offset[clist][index][comp] = offset[clist][index][comp];
-            //printf("%d %d\n",wp_weight[clist][index][comp],wp_offset[clist][index][comp]);
+            weight[clist][n][1] = default_weight[1];
+            weight[clist][n][2] = default_weight[2];        
+            offset[clist][n][1] = 0;
+            offset[clist][n][2] = 0;
+          }
+
+          for (i = 0; i < 3; i++)
+          {
+            wp_weight[clist][n][i] = weight[clist][n][i];
+            wp_offset[clist][n][i] = offset[clist][n][i];
+#if DEBUG_WP
+            printf("%d %d\n",wp_weight[clist][index][comp],wp_offset[clist][index][comp]);
+#endif
           }
         }
       }
     }
-    else
+
+    if (active_pps->weighted_bipred_idc != 1)
     {
       for (clist=0; clist<2 + list_offset; clist++)
       {
@@ -337,21 +396,22 @@ void estimate_weighting_factor_B_slice()
         }
       }
     }
+
+
     for (i = 0; i < listXsize[LIST_0]; i++)
     {
       for (j = 0; j < listXsize[LIST_1]; j++)
       {
         for (comp = 0; comp < 3; comp++)
         {
-          log_weight_denom = (comp == 0) ? luma_log_weight_denom : chroma_log_weight_denom;
           wbp_weight[0][i][j][comp] = wp_weight[0][i][comp];
           wbp_weight[1][i][j][comp] = wp_weight[1][j][comp];
         }
-        /*
+#if DEBUG_WP
         printf ("bpw weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n", i, j, wbp_weight[0][i][j][0], wbp_weight[1][i][j][0],
-        enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
-        DistScaleFactor ,tx,tx,tx);
-        */
+          enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
+          DistScaleFactor ,tx,tx,tx);
+#endif
       }
     }
   }
@@ -365,14 +425,16 @@ void estimate_weighting_factor_B_slice()
 ************************************************************************
 */
 
-int test_wp_P_slice(int select_offset)
+int TestWPPSliceAlg0(ImageParameters *img, InputParameters *params, int select_offset)
 {
-  int i, j, n;
+  int i, j, k, n;
 
   int index;
   int comp;
   double dc_org = 0.0;
+  double dc_org_UV[2] = {0.0};  
   double dc_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double dc_ref_UV[MAX_REFERENCE_PICTURES][2] = { {0.0}};
 
   int default_weight[3];
 
@@ -407,6 +469,14 @@ int test_wp_P_slice(int select_offset)
 
   dc_org = ComputeImgSum(pCurImg, img->height, img->width);
 
+  if (params->ChromaWeightSupport == 1)
+  {
+    for (k = 0; k < 2; k++)
+    {
+      dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+    } 
+  }
+
   for (clist = 0; clist < 2 + list_offset; clist++)
   {
     for (n = 0; n < listXsize[clist]; n++)
@@ -414,6 +484,15 @@ int test_wp_P_slice(int select_offset)
       tmpPtr = listX[clist][n]->p_curr_img;
       dc_ref[n] = ComputeImgSum(tmpPtr, img->height, img->width);
 
+      if (params->ChromaWeightSupport == 1)
+      {
+        for (k = 0; k < 2; k++)
+        {
+          tmpPtr = listX[clist][n]->imgUV[k];
+          dc_ref_UV[n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+        }        
+      }
+
       if (select_offset == 0)
       {
         if (dc_ref[n] != 0.0)
@@ -421,6 +500,20 @@ int test_wp_P_slice(int select_offset)
         else
           weight[clist][n][0] = default_weight[0];  // only used when reference picture is black
         weight[clist][n][0] = iClip3(-128, 127, weight[clist][n][0]);
+        if (params->ChromaWeightSupport == 1)
+        {
+          if (dc_ref_UV[n][0] != 0)
+            weight[clist][n][1] = (int) (default_weight[1] * dc_org_UV[0] / dc_ref_UV[n][0] + 0.5);
+          else
+            weight[clist][n][1] = default_weight[1];  // only used when reference picture is black
+          weight[clist][n][1] = iClip3(-128, 127, weight[clist][n][1]);
+
+          if (dc_ref_UV[n][1] != 0)
+            weight[clist][n][2] = (int) (default_weight[2] * dc_org_UV[1] / dc_ref_UV[n][1] + 0.5);
+          else
+            weight[clist][n][2] = default_weight[2];  // only used when reference picture is black
+          weight[clist][n][2] = iClip3(-64, 128, weight[clist][n][2]);
+        }
       }
       else
       {
@@ -429,6 +522,23 @@ int test_wp_P_slice(int select_offset)
         offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
         offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
         weight[clist][n][0] = default_weight[0];
+
+        if (params->ChromaWeightSupport == 1)
+        {
+            offset[clist][n][1] = (int) ((dc_org_UV[0] - dc_ref_UV[n][0])/(img->size_cr)+0.5);
+            offset[clist][n][1] = (offset[clist][n][1] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][1] = iClip3( -128, 127, offset[clist][n][1]);
+            offset[clist][n][1] = offset[clist][n][1]<<(img->bitdepth_chroma - 8);
+            
+            weight[clist][n][1] = default_weight[1];
+
+            offset[clist][n][2] = (int) ((dc_org_UV[1] - dc_ref_UV[n][1])/(img->size_cr)+0.5);
+            offset[clist][n][2] = (offset[clist][n][2] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][2] = iClip3( -128, 127, offset[clist][n][2]);
+            offset[clist][n][2] = offset[clist][n][2]<<(img->bitdepth_chroma - 8);
+
+            weight[clist][n][2] = default_weight[2];
+        }
       }
     }
   }
@@ -443,7 +553,7 @@ int test_wp_P_slice(int select_offset)
           ? iabs(offset[clist][index][comp]) > 2
           : offset[clist][index][comp] != 0;
 
-        if (weight[clist][index][comp] != default_weight[0] ||  offset_test)
+        if (weight[clist][index][comp] != default_weight[0] || offset_test)
         {
           perform_wp = 1;
           break;
@@ -460,22 +570,22 @@ int test_wp_P_slice(int select_offset)
 /*!
 ************************************************************************
 * \brief
-*    test_wp_B_slice:
+*    TestWPBSliceAlg0:
 *    Tests B slice weighting prediction
 ************************************************************************
 */
-int test_wp_B_slice(int select_method)
+int TestWPBSliceAlg0(ImageParameters *img, InputParameters *params, int select_method)
 {
-  int i, j, n;
+  int i, j, k, n;
 
   int tx,DistScaleFactor;
 
   int index;
   int comp;
   double dc_org = 0.0;
-  double dc_ref[6][MAX_REFERENCE_PICTURES] = { {0.0} };
-
-  int log_weight_denom;
+  double dc_org_UV[2] = { 0.0 };    
+  double dc_ref[6][MAX_REFERENCE_PICTURES] = { {0.0} };  
+  double dc_ref_UV[6][MAX_REFERENCE_PICTURES][2] = { {{0.0}} };
 
   int default_weight[3];
   // this needs to be fixed.
@@ -483,7 +593,6 @@ int test_wp_B_slice(int select_method)
   int weight[6][MAX_REFERENCE_PICTURES][3];
   int offset[6][MAX_REFERENCE_PICTURES][3];
   int im_weight[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
-  int im_offset[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
   int clist;
   int wf_weight, wf_offset;
   int perform_wp = 0;
@@ -533,21 +642,17 @@ int test_wp_B_slice(int select_method)
         // implicit weights
         if (td == 0)
         {
-          im_weight[1][i][j][comp] = default_weight[comp];
           im_weight[0][i][j][comp] = default_weight[comp];
-          im_offset[1][i][j][comp] = 0;
-          im_offset[0][i][j][comp] = 0;
+          im_weight[1][i][j][comp] = default_weight[comp];
         }
         else
         {
           tx = (16384 + iabs(td/2))/td;
           DistScaleFactor = iClip3(-1024, 1023, (tx*tb + 32 )>>6);
-          im_weight[1][i][j][comp] = DistScaleFactor>>2;
+          im_weight[1][i][j][comp] = DistScaleFactor >> 2;
           if (im_weight[1][i][j][comp] < -64 || im_weight[1][i][j][comp] >128)
             im_weight[1][i][j][comp] = default_weight[comp];
           im_weight[0][i][j][comp] = 64 - im_weight[1][i][j][comp];
-          im_offset[1][i][j][comp] = 0;
-          im_offset[0][i][j][comp] = 0;
         }
       }
     }
@@ -562,7 +667,6 @@ int test_wp_B_slice(int select_method)
       {
         for (comp = 0; comp < 3; comp++)
         {
-          log_weight_denom = (comp == 0) ? luma_log_weight_denom : chroma_log_weight_denom;
           wbp_weight[1][i][j][comp] = im_weight[1][i][j][comp] ;
           wbp_weight[0][i][j][comp] = im_weight[0][i][j][comp];
         }
@@ -573,12 +677,11 @@ int test_wp_B_slice(int select_method)
     {
       for (index = 0; index < listXsize[clist]; index++)
       {
-        wp_weight[clist][index][0] = default_weight[0];
-        wp_weight[clist][index][1] = default_weight[1];
-        wp_weight[clist][index][2] = default_weight[2];
-        wp_offset[clist][index][0] = 0;
-        wp_offset[clist][index][1] = 0;
-        wp_offset[clist][index][2] = 0;
+        for (comp = 0; comp < 3; comp++)
+        {
+          wp_weight[clist][index][comp] = default_weight[comp];
+          wp_offset[clist][index][comp] = 0;
+        }
       }
     }
   }
@@ -586,6 +689,14 @@ int test_wp_B_slice(int select_method)
   {
     dc_org = ComputeImgSum(pCurImg, img->height, img->width);
 
+    if (params->ChromaWeightSupport == 1)
+    {
+      for (k = 0; k < 2; k++)
+      {
+        dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+      } 
+    }
+
     for (clist=0; clist<2 + list_offset; clist++)
     {
       for (n = 0; n < listXsize[clist]; n++)
@@ -606,10 +717,32 @@ int test_wp_B_slice(int select_method)
         weight[clist][n][0] = wf_weight;
         offset[clist][n][0] = wf_offset;
 
-        weight[clist][n][1] = default_weight[1];
-        weight[clist][n][2] = default_weight[2];        
-        offset[clist][n][1] = 0;
-        offset[clist][n][2] = 0;
+        // UV
+        if (params->ChromaWeightSupport == 1)
+        {          
+          for (k = 0; k < 2; k++)
+          {
+            tmpPtr = listX[clist][n]->imgUV[k];
+            dc_ref_UV[clist][n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+
+            if (dc_ref_UV[clist][n][k] != 0.0)
+              wf_weight = (int) (default_weight[k + 1] * dc_org_UV[k] / dc_ref_UV[clist][n][k] + 0.5);
+            else
+              wf_weight = default_weight[k + 1];  // only used when reference picture is black
+            wf_weight = iClip3(-128, 127, wf_weight);
+            wf_offset = 0;
+
+            weight[clist][n][k + 1] = wf_weight;
+            offset[clist][n][k + 1] = wf_offset;
+          }
+        }
+        else
+        {
+          weight[clist][n][1] = default_weight[1];
+          weight[clist][n][2] = default_weight[2];        
+          offset[clist][n][1] = 0;
+          offset[clist][n][2] = 0;
+        }
       }
     }
 
@@ -635,21 +768,21 @@ int test_wp_B_slice(int select_method)
         }
       }
     }
+
     for (i = 0; i < listXsize[LIST_0]; i++)
     {
       for (j = 0; j < listXsize[LIST_1]; j++)
       {
         for (comp = 0; comp < 3; comp++)
         {
-          log_weight_denom = (comp == 0) ? luma_log_weight_denom : chroma_log_weight_denom;
           wbp_weight[0][i][j][comp] = wp_weight[0][i][comp];
           wbp_weight[1][i][j][comp] = wp_weight[1][j][comp];
         }
-        /*
+#if DEBUG_WP
         printf ("bpw weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n", i, j, wbp_weight[0][i][j][0], wbp_weight[1][i][j][0],
         enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
         DistScaleFactor ,tx,tx,tx);
-        */
+#endif
       }
     }
   }
@@ -658,8 +791,8 @@ int test_wp_B_slice(int select_method)
   {
     int active_refs[2];
 
-    active_refs[0] = (params->B_List0_refs == 0 ? listXsize[0] : imin(params->B_List0_refs,listXsize[0]));
-    active_refs[1] = (params->B_List1_refs == 0 ? listXsize[1] : imin(params->B_List0_refs,listXsize[1]));
+    active_refs[0] = (params->B_List0_refs == 0 ? listXsize[0] : imin(params->B_List0_refs, listXsize[0]));
+    active_refs[1] = (params->B_List1_refs == 0 ? listXsize[1] : imin(params->B_List1_refs, listXsize[1]));
 
     for (clist=0; clist<2 + list_offset; clist++)
     {
@@ -680,5 +813,3 @@ int test_wp_B_slice(int select_method)
   }
   return perform_wp;
 }
-
-
diff --git a/lencod/src/wp_lms.c b/lencod/src/wp_lms.c
new file mode 100644
index 0000000..e05d745
--- /dev/null
+++ b/lencod/src/wp_lms.c
@@ -0,0 +1,877 @@
+
+/*!
+*************************************************************************************
+* \file wp_lms.c
+*
+* \brief
+*    Estimate weights for WP using LMS method
+*
+* \author
+*    Main contributors (see contributors.h for copyright, address and affiliation details)
+*     - Alexis Michael Tourapis         <alexismt@ieee.org>
+*     - Athanasios Leontaris            <aleon@dolby.com>
+*************************************************************************************
+*/
+#include "contributors.h"
+
+#include "global.h"
+#include "image.h"
+#include "wp.h"
+
+static inline double ComputeNormMean(imgpel **CurrentImage, double mean_value, int height, int width)
+{
+  int i, j;
+  double sum_value = 0.0;
+
+  for (i = 0; i < height; i++)
+  {
+    for (j = 0; j < width; j++)
+    {
+      sum_value += dabs((double) CurrentImage[i][j] - mean_value);
+    }
+  }
+  return sum_value;
+}
+
+/*!
+************************************************************************
+* \brief
+*    Estimates reference picture weighting factors for P slices
+************************************************************************
+*/
+
+void EstimateWPPSliceAlg1(ImageParameters *img, InputParameters *params, int select_offset)
+{
+  double dc_org = 0.0;
+  double dc_org_UV[2] = {0.0};
+  double dc_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double dc_ref_UV[MAX_REFERENCE_PICTURES][2] = { {0.0}};
+  double norm_org = 0.0;
+  double norm_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double numer = {0.0};
+  double denom[MAX_REFERENCE_PICTURES] = {0.0};  
+
+  int i, n, k;
+  int default_weight[3];
+  int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
+  int weight[2][MAX_REFERENCE_PICTURES][3];
+  int offset[2][MAX_REFERENCE_PICTURES][3];
+  int clist;
+
+  imgpel **tmpPtr;
+
+  luma_log_weight_denom   = 5;
+  chroma_log_weight_denom = 5;
+
+  wp_luma_round           = 1 << (luma_log_weight_denom - 1);
+  wp_chroma_round         = 1 << (chroma_log_weight_denom - 1);
+  default_weight[0]       = 1 << luma_log_weight_denom;
+  default_weight[1]       = default_weight[2] = 1 << chroma_log_weight_denom;
+  
+  dc_org = ComputeImgSum(pCurImg, img->height, img->width);
+
+  norm_org = dc_org / ((double) img->size);
+  numer = ComputeNormMean(pCurImg, norm_org, img->height, img->width);
+
+  if (params->ChromaWeightSupport == 1)
+  {
+    for (k = 0; k < 2; k++)
+    {
+      dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+    } 
+  }
+
+  for (clist = 0; clist < 2 + list_offset; clist++)
+  {
+    for (n = 0; n < listXsize[clist]; n++)
+    {
+      if ( wpxDetermineWP( params, img, clist, n ) )
+      {
+        /* set all values to defaults */
+        for (i = 0; i < 3; i++)
+        {
+          weight[clist][n][i]    = default_weight[i];
+          wp_weight[clist][n][i] = default_weight[i];
+          wp_offset[clist][n][i] = 0;
+          offset[clist][n][i]    = 0;
+        }
+
+        // Y
+        tmpPtr = listX[clist][n]->p_curr_img;      
+        dc_ref[n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+        norm_ref[n] = dc_ref[n] / ((double) img->size);
+        denom[n] = ComputeNormMean(tmpPtr, norm_ref[n], img->height, img->width);
+
+        if (params->ChromaWeightSupport == 1)
+        {
+          for (k = 0; k < 2; k++)
+          {
+            // UV
+            tmpPtr = listX[clist][n]->imgUV[k];
+            dc_ref_UV[n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+          }        
+        }
+
+        if (select_offset == 0)
+        {
+          if (denom[n] != 0)
+            weight[clist][n][0] = (int) (default_weight[0] * numer / denom[n] + 0.5);
+          else
+            weight[clist][n][0] = default_weight[0];  // only used when reference picture is black
+          weight[clist][n][0] = iClip3(-128, 127, weight[clist][n][0]);
+
+          offset[clist][n][0] = (int) (norm_org - ((double) weight[clist][n][0] * norm_ref[n] / (double) default_weight[0]) + 0.5);
+          offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+          offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
+          offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
+
+          if (params->ChromaWeightSupport == 1)
+          {
+            if (dc_ref_UV[n][0] != 0)
+              weight[clist][n][1] = (int) (default_weight[1] * dc_org_UV[0] / dc_ref_UV[n][0] + 0.5);
+            else
+              weight[clist][n][1] = default_weight[1];  // only used when reference picture is black
+            weight[clist][n][1] = iClip3(-128, 127, weight[clist][n][1]);
+
+            if (dc_ref_UV[n][1] != 0)
+              weight[clist][n][2] = (int) (default_weight[2] * dc_org_UV[1] / dc_ref_UV[n][1] + 0.5);
+            else
+              weight[clist][n][2] = default_weight[2];  // only used when reference picture is black
+            weight[clist][n][2] = iClip3(-64, 128, weight[clist][n][2]);
+          }
+        }
+        else
+        {
+          offset[clist][n][0] = (int) ((dc_org - dc_ref[n])/(img->size)+0.5);
+          offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+          offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
+          offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
+          weight[clist][n][0] = default_weight[0];
+
+          if (params->ChromaWeightSupport == 1)
+          {
+            offset[clist][n][1] = (int) ((dc_org_UV[0] - dc_ref_UV[n][0])/(img->size_cr)+0.5);
+            offset[clist][n][1] = (offset[clist][n][1] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][1] = iClip3( -128, 127, offset[clist][n][1]);
+            offset[clist][n][1] = offset[clist][n][1]<<(img->bitdepth_chroma - 8);
+            
+            weight[clist][n][1] = default_weight[1];
+
+            offset[clist][n][2] = (int) ((dc_org_UV[1] - dc_ref_UV[n][1])/(img->size_cr)+0.5);
+            offset[clist][n][2] = (offset[clist][n][2] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][2] = iClip3( -128, 127, offset[clist][n][2]);
+            offset[clist][n][2] = offset[clist][n][2]<<(img->bitdepth_chroma - 8);
+
+            weight[clist][n][2] = default_weight[2];
+          }
+        }
+
+        for (i=0; i < 3; i ++)
+        {
+          wp_weight[clist][n][i] = weight[clist][n][i];
+          wp_offset[clist][n][i] = offset[clist][n][i];
+#if DEBUG_WP
+          printf("index %d component %d weight %d offset %d\n",n,i,weight[0][n][i],offset[0][n][i]);
+#endif
+        }
+      }
+    }
+  }
+}
+
+/*!
+************************************************************************
+* \brief
+*    Estimates reference picture weighting factors for B slices
+************************************************************************
+*/
+void EstimateWPBSliceAlg1(ImageParameters *img, InputParameters *params)
+{
+  int i, j, n;
+
+  int tx,DistScaleFactor;
+
+  int index;
+  int comp;
+  double dc_org = 0.0;
+  double dc_org_UV[2] = { 0.0 };
+  double dc_ref[6][MAX_REFERENCE_PICTURES] = { {0.0} };
+  double dc_ref_UV[6][MAX_REFERENCE_PICTURES][2] = { {{0.0}} };
+  double norm_org = 0.0;
+  double norm_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double numer = {0.0};
+  double denom[MAX_REFERENCE_PICTURES] = {0.0};
+  int k;
+
+  int default_weight[3];
+  int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
+  int weight[6][MAX_REFERENCE_PICTURES][3];
+  int offset[6][MAX_REFERENCE_PICTURES][3];
+  int im_weight[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
+  int clist;
+  int wf_weight, wf_offset;
+  imgpel **tmpPtr;
+
+  if (active_pps->weighted_bipred_idc == 2) //! implicit mode. Values are fixed and it is important to show it here
+  {
+    luma_log_weight_denom = 5;
+    chroma_log_weight_denom = 5;
+  }
+  else                                     //! explicit mode. Values can be changed for higher precision.
+  {
+    luma_log_weight_denom = 5;
+    chroma_log_weight_denom = 5;
+  }
+
+  wp_luma_round     = 1 << (luma_log_weight_denom - 1);
+  wp_chroma_round   = 1 << (chroma_log_weight_denom - 1);
+  default_weight[0] = 1 << luma_log_weight_denom;
+  default_weight[1] = 1 << chroma_log_weight_denom;
+  default_weight[2] = 1 << chroma_log_weight_denom;
+
+  if (active_pps->weighted_bipred_idc == 2) //! implicit mode
+  {
+    for (i = 0; i < listXsize[LIST_0]; i++)
+    {
+      for (j = 0; j < listXsize[LIST_1]; j++)
+      {
+        int td, tb;
+        td = iClip3(-128, 127,(listX[LIST_1][j]->poc - listX[LIST_0][i]->poc));
+        tb = iClip3(-128, 127,(enc_picture->poc - listX[LIST_0][i]->poc));
+        for (comp = 0; comp < 3; comp++)
+        {
+          // implicit weights
+          if (td == 0)
+          {
+            im_weight[0][i][j][comp] = default_weight[comp];
+            im_weight[1][i][j][comp] = default_weight[comp];
+          }
+          else
+          {
+            tx = (16384 + iabs(td/2))/td;
+            DistScaleFactor = iClip3(-1024, 1023, (tx*tb + 32 )>>6);
+            im_weight[1][i][j][comp] = DistScaleFactor>>2;
+            if (im_weight[1][i][j][comp] < -64 || im_weight[1][i][j][comp] >128)
+              im_weight[1][i][j][comp] = default_weight[comp];
+            im_weight[0][i][j][comp] = 64 - im_weight[1][i][j][comp];
+          }
+        }
+#if DEBUG_WP
+        printf ("%d imp weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n",enc_picture->poc, i, j,  im_weight[0][i][j][0], im_weight[1][i][j][0],
+        enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
+        DistScaleFactor ,tx,td,tb);
+#endif
+      }
+    }
+
+    for (k = 0; k < 2; k++)
+    {
+      for (i = 0; i < listXsize[LIST_0]; i++)
+      {
+        for (j = 0; j < listXsize[LIST_1]; j++)
+        {
+          for (comp = 0; comp < 3; comp++)
+          {
+            wbp_weight[k][i][j][comp] = im_weight[k][i][j][comp];
+          }
+        }
+      }
+    }
+
+    for (clist=0; clist<2 + list_offset; clist++)
+    {
+      for (index = 0; index < listXsize[clist]; index++)
+      {
+        for (comp = 0; comp < 3; comp++)
+        {
+          wp_weight[clist][index][comp] = default_weight[comp];
+          wp_offset[clist][index][comp] = 0;
+        }
+      }
+    }
+  }
+  else // explicit WP mode (or no WP at all)
+  {
+    dc_org = ComputeImgSum(pCurImg, img->height, img->width);
+
+    if (params->EnhancedBWeightSupport)
+    {
+      norm_org = dc_org / ((double) img->size);
+      numer = ComputeNormMean(pCurImg, norm_org, img->height, img->width);
+    }
+
+    if (params->ChromaWeightSupport == 1)
+    {
+      for (k = 0; k < 2; k++)
+      {
+        dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+      } 
+    }
+
+    for (clist=0; clist<2 + list_offset; clist++)
+    {
+      for (n = 0; n < listXsize[clist]; n++)
+      {
+        if ( wpxDetermineWP( params, img, clist, n ) )
+        {
+          /* set all values to defaults */
+          for (i = 0; i < 3; i++)
+          {
+            wp_weight[clist][n][i] = default_weight[i];
+            wp_offset[clist][n][i] = 0;
+            offset   [clist][n][i] = 0;
+            weight   [clist][n][i] = default_weight[i];
+          }
+          // To simplify these computations we may wish to perform these after a reference is 
+          // stored in the reference buffer and attach them to the storedimage structure!!!
+          // Y
+          tmpPtr = listX[clist][n]->p_curr_img;
+          dc_ref[clist][n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+          if (params->EnhancedBWeightSupport)
+          {
+            norm_ref[n] = dc_ref[clist][n] / ((double) img->size);
+            denom[n] = ComputeNormMean(tmpPtr, norm_ref[n], img->height, img->width);
+          }
+          if (params->EnhancedBWeightSupport)
+          {
+            if (denom[n] != 0)
+              wf_weight = (int) (default_weight[0] * numer / denom[n] + 0.5);
+            else
+              wf_weight = default_weight[0];  // only used when reference picture is black
+            wf_weight = iClip3(-128, 127, wf_weight);
+
+            wf_offset = (int) (norm_org - ((double) wf_weight * norm_ref[n] / (double) default_weight[0]) + 0.5);
+            wf_offset = (wf_offset + ((img->bitdepth_luma - 8)>>1))>>(img->bitdepth_luma-8);
+            wf_offset = iClip3( -128, 127, wf_offset);
+            wf_offset = wf_offset <<(img->bitdepth_luma - 8);
+          }
+          else
+          {
+            if (dc_ref[clist][n] != 0.0)
+              wf_weight = (int) (default_weight[0] * dc_org / dc_ref[clist][n] + 0.5);
+            else
+              wf_weight = default_weight[0];  // only used when reference picture is black
+            wf_weight = iClip3(-128, 127, wf_weight);
+            wf_offset = 0;
+          }
+
+          //    printf("dc_org = %d, dc_ref = %d, weight[%d] = %d\n",dc_org, dc_ref[n],n,weight[n][0]);
+
+          weight[clist][n][0] = wf_weight;
+          offset[clist][n][0] = wf_offset;
+
+          // UV
+          if (params->ChromaWeightSupport == 1)
+          {          
+            for (k = 0; k < 2; k++)
+            {        	
+              tmpPtr = listX[clist][n]->imgUV[k];
+              dc_ref_UV[clist][n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+
+              if (dc_ref_UV[clist][n][k] != 0.0)
+                wf_weight = (int) (default_weight[k + 1] * dc_org_UV[k] / dc_ref_UV[clist][n][k] + 0.5);
+              else
+                wf_weight = default_weight[k + 1];  // only used when reference picture is black
+              wf_weight = iClip3(-128, 127, wf_weight);
+              wf_offset = 0;
+
+              weight[clist][n][k + 1] = wf_weight;
+              offset[clist][n][k + 1] = wf_offset;
+            }
+          }
+          else
+          {
+            weight[clist][n][1] = default_weight[1];
+            weight[clist][n][2] = default_weight[2];        
+            offset[clist][n][1] = 0;
+            offset[clist][n][2] = 0;
+          }
+
+          for (i = 0; i < 3; i++)
+          {
+            wp_weight[clist][n][i] = weight[clist][n][i];
+            wp_offset[clist][n][i] = offset[clist][n][i];
+#if DEBUG_WP
+            printf("%d %d\n",wp_weight[clist][index][comp],wp_offset[clist][index][comp]);
+#endif
+          }
+        }
+      }
+    }
+
+    if (active_pps->weighted_bipred_idc != 1)
+    {
+      for (clist=0; clist<2 + list_offset; clist++)
+      {
+        for (index = 0; index < listXsize[clist]; index++)
+        {
+          memcpy(wp_weight[clist][index], default_weight, 3 * sizeof(int));
+          memset(wp_offset[clist][index], 0, 3 * sizeof(int));
+        }
+      }
+    }
+
+    for (i = 0; i < listXsize[LIST_0]; i++)
+    {
+      for (j = 0; j < listXsize[LIST_1]; j++)
+      {
+        for (comp = 0; comp < 3; comp++)
+        {
+          wbp_weight[0][i][j][comp] = wp_weight[0][i][comp];
+          wbp_weight[1][i][j][comp] = wp_weight[1][j][comp];
+        }
+#if DEBUG_WP
+        printf ("bpw weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n", i, j, wbp_weight[0][i][j][0], wbp_weight[1][i][j][0],
+        enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
+        DistScaleFactor ,tx,tx,tx);
+#endif
+      }
+    }
+  }
+}
+
+
+/*!
+************************************************************************
+* \brief
+*    Tests P slice weighting factors to perform or not WP RD decision
+************************************************************************
+*/
+
+int TestWPPSliceAlg1(ImageParameters *img, InputParameters *params, int select_offset)
+{
+  int i, j, k, n;
+
+  int index;
+  int comp;
+  double dc_org = 0.0;
+  double dc_org_UV[2] = {0.0};  
+  double dc_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double dc_ref_UV[MAX_REFERENCE_PICTURES][2] = { {0.0}};
+  double norm_org = 0.0;
+  double norm_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double numer = {0.0};
+  double denom[MAX_REFERENCE_PICTURES] = {0.0};
+
+  int default_weight[3];
+
+  int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
+  int weight[2][MAX_REFERENCE_PICTURES][3];
+  int offset[2][MAX_REFERENCE_PICTURES][3];
+  int clist;
+  int perform_wp = 0;
+  imgpel **tmpPtr;
+
+  luma_log_weight_denom =   5;
+  chroma_log_weight_denom = 5;
+  wp_luma_round     = 1 << (luma_log_weight_denom - 1);
+  wp_chroma_round   = 1 << (chroma_log_weight_denom - 1);
+  default_weight[0] = 1 << luma_log_weight_denom;
+  default_weight[1] = default_weight[2] = 1 << chroma_log_weight_denom;
+
+  /* set all values to defaults */
+  for (i = 0; i < 2 + list_offset; i++)
+  {
+    for (j = 0; j < listXsize[i]; j++)
+    {
+      for (n = 0; n < 3; n++)
+      {
+        weight[i][j][n] = default_weight[n];
+        wp_weight[i][j][n] = default_weight[n];
+        wp_offset[i][j][n] = 0;
+        offset[i][j][n] = 0;
+      }
+    }
+  }
+
+  dc_org = ComputeImgSum(pCurImg, img->height, img->width);
+
+  norm_org = dc_org / ((double) img->size);
+  numer = ComputeNormMean(pCurImg, norm_org, img->height, img->width);
+
+  if (params->ChromaWeightSupport == 1)
+  {
+    for (k = 0; k < 2; k++)
+    {
+      dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+    } 
+  }
+
+  for (clist = 0; clist < 2 + list_offset; clist++)
+  {
+    for (n = 0; n < listXsize[clist]; n++)
+    {
+      tmpPtr = listX[clist][n]->p_curr_img;
+      dc_ref[n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+      norm_ref[n] = dc_ref[n] / ((double) img->size);
+      denom[n] = ComputeNormMean(tmpPtr, norm_ref[n], img->height, img->width);
+
+      if (params->ChromaWeightSupport == 1)
+      {
+        for (k = 0; k < 2; k++)
+        {
+          tmpPtr = listX[clist][n]->imgUV[k];
+          dc_ref_UV[n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+        }        
+      }
+
+      if (select_offset == 0)
+      {
+        if (denom[n] != 0)
+          weight[clist][n][0] = (int) (default_weight[0] * numer / denom[n] + 0.5);
+        else
+          weight[clist][n][0] = default_weight[0];  // only used when reference picture is black
+        weight[clist][n][0] = iClip3(-128, 127, weight[clist][n][0]);
+
+        offset[clist][n][0] = (int) (norm_org - ((double) weight[clist][n][0] * norm_ref[n] / (double) default_weight[0]) + 0.5);
+        offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+        offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
+        offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);       
+
+        if (params->ChromaWeightSupport == 1)
+        {
+          if (dc_ref_UV[n][0] != 0)
+            weight[clist][n][1] = (int) (default_weight[1] * dc_org_UV[0] / dc_ref_UV[n][0] + 0.5);
+          else
+            weight[clist][n][1] = default_weight[1];  // only used when reference picture is black
+          weight[clist][n][1] = iClip3(-128, 127, weight[clist][n][1]);
+
+          if (dc_ref_UV[n][1] != 0)
+            weight[clist][n][2] = (int) (default_weight[2] * dc_org_UV[1] / dc_ref_UV[n][1] + 0.5);
+          else
+            weight[clist][n][2] = default_weight[2];  // only used when reference picture is black
+          weight[clist][n][2] = iClip3(-64, 128, weight[clist][n][2]);
+        }
+      }
+      else
+      {
+        offset[clist][n][0] = (int) ((dc_org - dc_ref[n])/(img->size)+0.5);
+        offset[clist][n][0] = (offset[clist][n][0]+((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+        offset[clist][n][0] = iClip3( -128, 127, offset[clist][n][0]);
+        offset[clist][n][0] = offset[clist][n][0]<<(img->bitdepth_luma-8);
+        weight[clist][n][0] = default_weight[0];
+
+        if (params->ChromaWeightSupport == 1)
+        {
+            offset[clist][n][1] = (int) ((dc_org_UV[0] - dc_ref_UV[n][0])/(img->size_cr)+0.5);
+            offset[clist][n][1] = (offset[clist][n][1] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][1] = iClip3( -128, 127, offset[clist][n][1]);
+            offset[clist][n][1] = offset[clist][n][1]<<(img->bitdepth_chroma - 8);
+            
+            weight[clist][n][1] = default_weight[1];
+
+            offset[clist][n][2] = (int) ((dc_org_UV[1] - dc_ref_UV[n][1])/(img->size_cr)+0.5);
+            offset[clist][n][2] = (offset[clist][n][2] + ((img->bitdepth_chroma - 8)>>1))>>(img->bitdepth_chroma-8);
+            offset[clist][n][2] = iClip3( -128, 127, offset[clist][n][2]);
+            offset[clist][n][2] = offset[clist][n][2]<<(img->bitdepth_chroma - 8);
+
+            weight[clist][n][2] = default_weight[2];
+        }
+      }
+    }
+  }
+
+  for (clist=0; clist<2 + list_offset; clist++)
+  {
+    for (index = 0; index < listXsize[clist]; index++)
+    {
+      for (comp=0; comp < 3; comp ++)
+      {
+        int offset_test = params->RDPSliceBTest && active_sps->profile_idc != 66
+          ? iabs(offset[clist][index][comp]) > 2
+          : offset[clist][index][comp] != 0;
+
+        if (weight[clist][index][comp] != default_weight[0] || offset_test)
+        {
+          perform_wp = 1;
+          break;
+        }
+      }
+      if (perform_wp == 1) break;
+    }
+    if (perform_wp == 1) break;
+  }
+
+  return perform_wp;
+}
+
+/*!
+************************************************************************
+* \brief
+*    TestWPBSliceAlg1:
+*    Tests B slice weighting prediction
+************************************************************************
+*/
+int TestWPBSliceAlg1(ImageParameters *img, InputParameters *params, int select_method)
+{
+  int i, j, k, n;
+
+  int tx,DistScaleFactor;
+
+  int index;
+  int comp;
+  double dc_org = 0.0;
+  double dc_org_UV[2] = { 0.0 };    
+  double dc_ref[6][MAX_REFERENCE_PICTURES] = { {0.0} };  
+  double dc_ref_UV[6][MAX_REFERENCE_PICTURES][2] = { {{0.0}} };
+  double norm_org = 0.0;
+  double norm_ref[MAX_REFERENCE_PICTURES] = { 0.0 };
+  double numer = {0.0};
+  double denom[MAX_REFERENCE_PICTURES] = {0.0};
+
+  int default_weight[3];
+  // this needs to be fixed.
+  int list_offset   = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
+  int weight[6][MAX_REFERENCE_PICTURES][3];
+  int offset[6][MAX_REFERENCE_PICTURES][3];
+  int im_weight[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES][3];
+  int clist;
+  int wf_weight, wf_offset;
+  int perform_wp = 0;
+  imgpel **tmpPtr;
+
+  if (select_method == 1) //! implicit mode
+  {
+    luma_log_weight_denom = 5;
+    chroma_log_weight_denom = 5;
+  }
+  else
+  {
+    luma_log_weight_denom = 5;
+    chroma_log_weight_denom = 5;
+  }
+
+  wp_luma_round     = 1 << (luma_log_weight_denom - 1);
+  wp_chroma_round   = 1 << (chroma_log_weight_denom - 1);
+  default_weight[0] = 1 << luma_log_weight_denom;
+  default_weight[1] = 1 << chroma_log_weight_denom;
+  default_weight[2] = 1 << chroma_log_weight_denom;
+
+  /* set all values to defaults */
+  for (i = 0; i < 2 + list_offset; i++)
+  {
+    for (j = 0; j < listXsize[i]; j++)
+    {
+      for (n = 0; n < 3; n++)
+      {
+        wp_weight[i][j][n] = default_weight[n];
+        wp_offset[i][j][n] = 0;
+        offset   [i][j][n] = 0;
+        weight   [i][j][n] = default_weight[n];
+      }
+    }
+  }
+
+  for (i = 0; i < listXsize[LIST_0]; i++)
+  {
+    for (j = 0; j < listXsize[LIST_1]; j++)
+    {
+      int td, tb;
+      td = iClip3(-128, 127,(listX[LIST_1][j]->poc - listX[LIST_0][i]->poc));
+      tb = iClip3(-128, 127,(enc_picture->poc - listX[LIST_0][i]->poc));
+      for (comp = 0; comp < 3; comp++)
+      {
+        // implicit weights
+        if (td == 0)
+        {
+          im_weight[0][i][j][comp] = default_weight[comp];
+          im_weight[1][i][j][comp] = default_weight[comp];
+        }
+        else
+        {
+          tx = (16384 + iabs(td/2))/td;
+          DistScaleFactor = iClip3(-1024, 1023, (tx*tb + 32 )>>6);
+          im_weight[1][i][j][comp] = DistScaleFactor >> 2;
+          if (im_weight[1][i][j][comp] < -64 || im_weight[1][i][j][comp] >128)
+            im_weight[1][i][j][comp] = default_weight[comp];
+          im_weight[0][i][j][comp] = 64 - im_weight[1][i][j][comp];
+        }
+      }
+    }
+  }
+
+
+  if (select_method == 1) //! implicit mode
+  {
+    for (i = 0; i < listXsize[LIST_0]; i++)
+    {
+      for (j = 0; j < listXsize[LIST_1]; j++)
+      {
+        for (comp = 0; comp < 3; comp++)
+        {
+          wbp_weight[1][i][j][comp] = im_weight[1][i][j][comp] ;
+          wbp_weight[0][i][j][comp] = im_weight[0][i][j][comp];
+        }
+      }
+    }
+
+    for (clist=0; clist<2 + list_offset; clist++)
+    {
+      for (index = 0; index < listXsize[clist]; index++)
+      {
+        for (comp = 0; comp < 3; comp++)
+        {
+          wp_weight[clist][index][comp] = default_weight[comp];
+          wp_offset[clist][index][comp] = 0;
+        }
+      }
+    }
+  }
+  else
+  {
+    dc_org = ComputeImgSum(pCurImg, img->height, img->width);
+
+    if (params->EnhancedBWeightSupport)
+    {
+      norm_org = dc_org / ((double) img->size);
+      numer = ComputeNormMean(pCurImg, norm_org, img->height, img->width);
+    }
+
+    if (params->ChromaWeightSupport == 1)
+    {
+      for (k = 0; k < 2; k++)
+      {
+        dc_org_UV[k] = ComputeImgSum(pImgOrg[k + 1], img->height_cr, img->width_cr);
+      } 
+    }
+
+    for (clist=0; clist<2 + list_offset; clist++)
+    {
+      for (n = 0; n < listXsize[clist]; n++)
+      {
+        // To simplify these computations we may wish to perform these after a reference is 
+        // stored in the reference buffer and attach them to the storedimage structure!!!
+        // Y
+        tmpPtr = listX[clist][n]->p_curr_img;
+        dc_ref[clist][n] = ComputeImgSum(tmpPtr, img->height, img->width);
+
+        if (params->EnhancedBWeightSupport)
+        {
+          norm_ref[n] = dc_ref[clist][n] / ((double) img->size);
+          denom[n] = ComputeNormMean(tmpPtr, norm_ref[n], img->height, img->width);
+
+          if (denom[n] != 0)
+            wf_weight = (int) (default_weight[0] * numer / denom[n] + 0.5);
+          else
+            wf_weight = default_weight[0];  // only used when reference picture is black
+          wf_weight = iClip3(-128, 127, wf_weight);
+
+          wf_offset = (int) (norm_org - ((double) wf_weight * norm_ref[n] / (double) default_weight[0]) + 0.5);
+          wf_offset = (wf_offset  + ((img->bitdepth_luma-8)>>1))>>(img->bitdepth_luma-8);
+          wf_offset = iClip3( -128, 127, wf_offset);
+          wf_offset = wf_offset <<(img->bitdepth_luma - 8);
+        }
+        else
+        {
+          if (dc_ref[clist][n] != 0.0)
+            wf_weight = (int) (default_weight[0] * dc_org / dc_ref[clist][n] + 0.5);
+          else
+            wf_weight = default_weight[0];  // only used when reference picture is black
+          wf_weight = iClip3(-128, 127, wf_weight);
+          wf_offset = 0;
+        }
+
+        weight[clist][n][0] = wf_weight;
+        offset[clist][n][0] = wf_offset;
+
+        // UV
+        if (params->ChromaWeightSupport == 1)
+        {          
+          for (k = 0; k < 2; k++)
+          {
+            tmpPtr = listX[clist][n]->imgUV[k];
+            dc_ref_UV[clist][n][k] = ComputeImgSum(tmpPtr, img->height_cr, img->width_cr);
+
+            if (dc_ref_UV[clist][n][k] != 0.0)
+              wf_weight = (int) (default_weight[k + 1] * dc_org_UV[k] / dc_ref_UV[clist][n][k] + 0.5);
+            else
+              wf_weight = default_weight[k + 1];  // only used when reference picture is black
+            wf_weight = iClip3(-128, 127, wf_weight);
+            wf_offset = 0;
+
+            weight[clist][n][k + 1] = wf_weight;
+            offset[clist][n][k + 1] = wf_offset;
+          }
+        }
+        else
+        {
+          weight[clist][n][1] = default_weight[1];
+          weight[clist][n][2] = default_weight[2];        
+          offset[clist][n][1] = 0;
+          offset[clist][n][2] = 0;
+        }
+      }
+    }
+
+    if (select_method == 0) //! explicit mode
+    {
+      for (clist=0; clist<2 + list_offset; clist++)
+      {
+        for (index = 0; index < listXsize[clist]; index++)
+        {
+          memcpy(wp_weight[clist][index], weight[clist][index], 3 * sizeof(int));
+          memcpy(wp_offset[clist][index], offset[clist][index], 3 * sizeof(int));
+        }
+      }
+    }
+    else
+    {
+      for (clist=0; clist<2 + list_offset; clist++)
+      {
+        for (index = 0; index < listXsize[clist]; index++)
+        {
+          memcpy(wp_weight[clist][index], default_weight, 3 * sizeof(int));
+          memset(wp_offset[clist][index], 0, 3 * sizeof(int));
+        }
+      }
+    }
+
+    for (i = 0; i < listXsize[LIST_0]; i++)
+    {
+      for (j = 0; j < listXsize[LIST_1]; j++)
+      {
+        for (comp = 0; comp < 3; comp++)
+        {
+          wbp_weight[0][i][j][comp] = wp_weight[0][i][comp];
+          wbp_weight[1][i][j][comp] = wp_weight[1][j][comp];
+        }
+#if DEBUG_WP
+        printf ("bpw weight[%d][%d] = %d  , %d (%d %d %d) (%d %d) (%d %d)\n", i, j, wbp_weight[0][i][j][0], wbp_weight[1][i][j][0],
+        enc_picture->poc,listX[LIST_0][i]->poc, listX[LIST_1][j]->poc,
+        DistScaleFactor ,tx,tx,tx);
+#endif
+      }
+    }
+  }
+
+  if (select_method == 0) //! implicit mode
+  {
+    int active_refs[2];
+
+    active_refs[0] = (params->B_List0_refs == 0 ? listXsize[0] : imin(params->B_List0_refs, listXsize[0]));
+    active_refs[1] = (params->B_List1_refs == 0 ? listXsize[1] : imin(params->B_List1_refs, listXsize[1]));
+
+    for (clist=0; clist<2 + list_offset; clist++)
+    {
+      for (index = 0; index < active_refs[clist]; index++)
+      {
+        for (comp=0; comp < 3; comp ++)
+        {
+          if (wp_weight[clist][index][comp] != default_weight[comp])
+          {
+            perform_wp = 1;
+            break;
+          }
+        }
+        if (perform_wp == 1) break;
+      }
+      if (perform_wp == 1) break;
+    }
+  }
+  return perform_wp;
+}
+
+
diff --git a/lencod/src/wp_mcprec.c b/lencod/src/wp_mcprec.c
new file mode 100644
index 0000000..59c1ef8
--- /dev/null
+++ b/lencod/src/wp_mcprec.c
@@ -0,0 +1,430 @@
+
+/*!
+*************************************************************************************
+* \file wp_mcprec.c
+*
+* \brief
+*    Improved Motion Compensation Precision Scheme using Weighted Prediction
+*
+* \author
+*    Main contributors (see contributors.h for copyright, address and affiliation details)
+*     - Athanasios Leontaris            <aleon@dolby.com>
+*     - Alexis Michael Tourapis         <alexismt@ieee.org>
+*************************************************************************************
+*/
+#include "contributors.h"
+
+#include "global.h"
+#include "image.h"
+#include "slice.h"
+#include "wp_mcprec.h"
+
+/*!
+************************************************************************
+* \brief
+*    Initialize WPR object structure
+* \para
+************************************************************************
+*/
+
+void wpxInitWPXObject( void )
+{
+  pWPX = (WPXObject *)malloc( sizeof( WPXObject ) );
+  if ( pWPX == NULL )
+  {
+    fprintf( stderr, "\n Error initializing memory for WPXObject. Exiting...\n" );
+    exit(1);
+  }
+
+  // wp_ref_l0
+  if ((pWPX->wp_ref_list[LIST_0] = (WeightedPredRefX *) calloc(MAX_REFERENCE_PICTURES, sizeof(WeightedPredRefX))) == NULL)
+    no_mem_exit("wpxInitWPXObject: pWPX->wp_ref_list[0]");
+  // wp_ref_l1
+  if ((pWPX->wp_ref_list[LIST_1] = (WeightedPredRefX *) calloc(MAX_REFERENCE_PICTURES, sizeof(WeightedPredRefX))) == NULL)
+    no_mem_exit("wpxInitWPXObject: pWPX->wp_ref_list[1]");
+}
+
+/*!
+************************************************************************
+* \brief
+*    Free WPR object structure
+* \para
+************************************************************************
+*/
+
+void wpxFreeWPXObject( void )
+{
+  if ( pWPX != NULL )
+  {
+    free( pWPX );
+  }
+
+  // wp_ref_l0
+  if (pWPX->wp_ref_list[LIST_0])
+    free(pWPX->wp_ref_list[LIST_0]);
+  pWPX->wp_ref_list[LIST_0] = NULL;
+  // wp_ref_l1
+  if (pWPX->wp_ref_list[LIST_1])
+    free(pWPX->wp_ref_list[LIST_1]);
+  pWPX->wp_ref_list[LIST_1] = NULL;
+}
+
+/*!
+************************************************************************
+* \brief
+*    Initialize WPR coding passes
+* \para
+************************************************************************
+*/
+
+void wpxInitWPXPasses( InputParameters *params )
+{
+  // initialize number of wp reference frames in each list
+  pWPX->num_wp_ref_list[LIST_0] = 0;
+  pWPX->num_wp_ref_list[LIST_1] = 0;
+
+  switch( params->WPMCPrecision )
+  {
+  default:
+  case 0:
+    break;
+  case 1:
+    pWPX->wp_rd_passes[0].algorithm = WP_REGULAR;
+    pWPX->wp_rd_passes[1].algorithm = WP_MCPREC_MINUS0;      
+    break;
+  case 2:
+    pWPX->wp_rd_passes[0].algorithm = WP_REGULAR;
+    pWPX->wp_rd_passes[1].algorithm = WP_MCPREC_MINUS0;
+    pWPX->wp_rd_passes[2].algorithm = WP_MCPREC_MINUS1;      
+    break;
+  }
+}
+
+/*!
+************************************************************************
+* \brief
+*    Modifies ref_pic_list for all lists
+************************************************************************
+*/
+
+void wpxModifyRefPicList( ImageParameters *img )
+{
+  unsigned int i, j, cloned_refs;
+  static int   default_order_list0[32];
+  static int   default_order_list1[32];
+  static int   re_order[32], *list_order;  
+  int          pred_list;
+
+  StorablePicture **list;
+
+  // set memory
+  memset( (void *)default_order_list0, 1<<20, 32 * sizeof( int ) );
+  memset( (void *)default_order_list1, 1<<20, 32 * sizeof( int ) );
+  memset( (void *)re_order,            1<<20, 32 * sizeof( int ) );
+
+  // First assign default list orders
+  list = listX[LIST_0];
+  for (i=0; i<(unsigned int)(img->num_ref_idx_l0_active); i++)
+  {
+    default_order_list0[i] = list[i]->pic_num;
+  }
+  if ( img->type == B_SLICE )
+  {
+    list = listX[LIST_1];
+    for (i=0; i<(unsigned int)(img->num_ref_idx_l1_active); i++)
+    {
+      default_order_list1[i] = list[i]->pic_num;
+    }
+  }
+
+  // obtain the ref_pic_list using POC-based reordering if img->type != B_SLICE
+  if ( img->type == P_SLICE )
+  {
+    int  list_sign[32];
+    int  poc_diff[32];
+    int  tmp_value;
+    int  abs_poc_dist;
+    
+    for (i=0; i<dpb.ref_frames_in_buffer; i++)
+    {
+      re_order[i] = dpb.fs_ref[i]->frame->pic_num;
+      if (dpb.fs_ref[i]->is_used==3 && (dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
+      {
+        abs_poc_dist = iabs(dpb.fs_ref[i]->frame->poc - enc_picture->poc) ;
+        poc_diff[i]  = abs_poc_dist;
+        list_sign[i] = (enc_picture->poc < dpb.fs_ref[i]->frame->poc) ? +1 : -1;
+      }
+    }
+
+    // sort these references based on poc (temporal) distance
+    for (i=0; i< dpb.ref_frames_in_buffer-1; i++)
+    {
+      for (j=i+1; j< dpb.ref_frames_in_buffer; j++)
+      {
+        if (poc_diff[i]>poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
+        {
+          tmp_value = poc_diff[i];
+          poc_diff[i] = poc_diff[j];
+          poc_diff[j] = tmp_value;
+          tmp_value  = re_order[i];
+          re_order[i] = re_order[j];
+          re_order[j] = tmp_value ;
+          tmp_value  = list_sign[i];
+          list_sign[i] = list_sign[j];
+          list_sign[j] = tmp_value ;
+        }
+      }
+    }
+  }
+  // end of POC-based reordering of P_SLICE
+
+  // loop over two lists
+  for ( pred_list = 0; pred_list < (1 + ( img->type == B_SLICE ? 1 : 0 )); pred_list++ )
+  {
+    if ( pred_list == LIST_0 )
+    {
+      list_order = (img->type == P_SLICE) ? re_order : default_order_list0;
+    }
+    else
+    {
+      list_order = default_order_list1;
+    }
+
+    // check algorithms (more flexibility for the future...)
+    switch( pWPX->curr_wp_rd_pass->algorithm )
+    {
+    default:
+    case WP_MCPREC_PLUS0:
+    case WP_MCPREC_PLUS1:
+    case WP_MCPREC_MINUS0:
+    case WP_MCPREC_MINUS1:
+      // ref 0 and 1 point to to the same reference
+      cloned_refs = pWPX->num_wp_ref_list[pred_list] = 2;
+      for ( j = 0; j < cloned_refs; j++ )
+      {
+        pWPX->wp_ref_list[pred_list][j].PicNum = list_order[0];
+      }
+      // shift the rest
+      for ( j = cloned_refs; j < dpb.ref_frames_in_buffer; j++ )
+      {
+        pWPX->wp_ref_list[pred_list][j].PicNum = list_order[j - (cloned_refs - 1)];
+        pWPX->num_wp_ref_list[pred_list]++;
+      }
+      break;
+    case WP_MCPREC_MINUS_PLUS0:
+      // ref 0 and 1 point to to the same reference
+      cloned_refs = pWPX->num_wp_ref_list[pred_list] = 3;
+      for ( j = 0; j < cloned_refs; j++ )
+      {
+        pWPX->wp_ref_list[pred_list][j].PicNum = list_order[0];
+      }
+      // shift the rest
+      for ( j = cloned_refs; j < dpb.ref_frames_in_buffer; j++ )
+      {
+        pWPX->wp_ref_list[pred_list][j].PicNum = list_order[j - (cloned_refs - 1)];
+        pWPX->num_wp_ref_list[pred_list]++;
+      }      
+      break;
+    }
+    // constrain list length
+    pWPX->num_wp_ref_list[pred_list] = imin( pWPX->num_wp_ref_list[pred_list],
+      ( pred_list == LIST_0 ) ? img->num_ref_idx_l0_active : img->num_ref_idx_l1_active );
+  }
+}
+
+/*!
+************************************************************************
+* \brief
+*    Determine whether it is fine to determine WP parameters
+************************************************************************
+*/
+
+int wpxDetermineWP( InputParameters *params, ImageParameters *img, int clist, int n )
+{
+  int i, j, determine_wp = 0;
+  int default_weight[3];
+  // we assume it's the same as in the WP functions
+  int luma_log_weight_denom   = 5;
+  int chroma_log_weight_denom = 5;
+  int cur_list = LIST_0;
+
+  default_weight[0] = 1 << luma_log_weight_denom;
+  default_weight[1] = 1 << chroma_log_weight_denom;
+  default_weight[2] = 1 << chroma_log_weight_denom;
+
+  if ( !params->WPMCPrecision )
+  {
+    determine_wp = 1;
+  }
+  else
+  {
+    determine_wp = 0;
+    // check slice type
+    if ( img->type == P_SLICE )
+    {
+      for (i = 0; i < 3; i++)
+      {
+        wp_weight[clist][n][i] = default_weight[i];
+      }      
+    }
+    else if ( img->type == B_SLICE )
+    {
+      cur_list = ((clist % 2) ==  LIST_1) ? LIST_0 : LIST_1;
+
+      // single-list prediction
+      for (i = 0; i < 3; i++)
+      {
+        wp_weight[clist][n][i] = default_weight[i];
+      }
+      // bi-pred
+      for (j = 0; j < listXsize[cur_list]; j++)
+      {
+        for (i = 0; i < 3; i++)
+          wbp_weight[clist][n][j][i] = default_weight[i];
+      }      
+    }
+    // algorithm consideration
+    switch( pWPX->curr_wp_rd_pass->algorithm )
+    {
+    case WP_MCPREC_PLUS0:
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] = (n == 1) ? 1 : 0;
+      break;
+    case WP_MCPREC_MINUS0:
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] = (n == 1) ? -1 : 0;
+      break;
+    case WP_MCPREC_PLUS1:
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] = (n == 0) ? 1 : 0;
+      break;
+    case WP_MCPREC_MINUS1:
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] = (n == 0) ? -1 : 0;
+      break;
+    case WP_MCPREC_MINUS_PLUS0:
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] = (n == 1) ? -1 : ((n == 2) ? 1 : 0);
+      break;
+    default:
+    case WP_REGULAR:
+      determine_wp = 1;
+      break;
+    }    
+    // check list (play with the WP factors)
+    if ( img->type == B_SLICE && cur_list == LIST_0 )
+    {
+      for (i = 0; i < 3; i++)
+        wp_offset[clist][n][i] *= 2;
+    }
+    // zero out chroma offsets
+    for (i = 1; i < 3; i++)
+    {
+      wp_offset[clist][n][i] = 0;
+    }
+  }
+
+  return determine_wp;
+}
+
+/*!
+************************************************************************
+* \brief
+*    Modify number of references
+************************************************************************
+*/
+
+void wpxAdaptRefNum( ImageParameters *img )
+{
+  if ( pWPX->curr_wp_rd_pass->algorithm == WP_REGULAR )
+  {
+    switch( img->type )
+    {
+    default:
+    case I_SLICE:
+      break;
+    case P_SLICE:
+      if ( img->num_ref_idx_l0_active == ( params->P_List0_refs * ((img->structure !=0) + 1) ) )
+      {
+        listXsize[LIST_0] = img->num_ref_idx_l0_active = imax( ((img->structure !=0) + 1), img->num_ref_idx_l0_active - ((img->structure !=0) + 1) );
+      }
+      break;
+    case B_SLICE:
+      if ( img->num_ref_idx_l0_active == ( params->B_List0_refs * ((img->structure !=0) + 1) ) )
+      {
+        listXsize[LIST_0] = img->num_ref_idx_l0_active = imax( ((img->structure !=0) + 1), img->num_ref_idx_l0_active - ((img->structure !=0) + 1) );
+      }
+      if ( img->num_ref_idx_l1_active == ( params->B_List1_refs * ((img->structure !=0) + 1) ) )
+      {
+        listXsize[LIST_1] = img->num_ref_idx_l1_active = imax( ((img->structure !=0) + 1), img->num_ref_idx_l1_active - ((img->structure !=0) + 1) );
+      }
+      break;
+    }    
+  }
+}
+
+/*!
+************************************************************************
+* \brief
+*    Reorder lists
+************************************************************************
+*/
+
+void wpxReorderLists( ImageParameters *img, Slice *currSlice )
+{
+  int i, num_ref;
+
+  wpxModifyRefPicList( img );
+
+  alloc_ref_pic_list_reordering_buffer(currSlice);
+
+  for (i = 0; i < img->num_ref_idx_l0_active + 1; i++)
+  {
+    currSlice->reordering_of_pic_nums_idc_l0[i] = 3;
+    currSlice->abs_diff_pic_num_minus1_l0[i] = 0;
+    currSlice->long_term_pic_idx_l0[i] = 0;
+  }
+
+  if (img->type == B_SLICE) // type should be part of currSlice not img
+  {
+    for (i = 0; i < img->num_ref_idx_l1_active + 1; i++)
+    {
+      currSlice->reordering_of_pic_nums_idc_l1[i] = 3;
+      currSlice->abs_diff_pic_num_minus1_l1[i] = 0;
+      currSlice->long_term_pic_idx_l1[i] = 0;
+    }
+  }
+
+  // LIST_0
+  num_ref = img->num_ref_idx_l0_active;
+
+  poc_ref_pic_reorder_frame(listX[LIST_0], num_ref,
+    currSlice->reordering_of_pic_nums_idc_l0,
+    currSlice->abs_diff_pic_num_minus1_l0,
+    currSlice->long_term_pic_idx_l0, LIST_0);
+  // reference picture reordering
+  reorder_ref_pic_list(listX[LIST_0], &listXsize[LIST_0],
+    img->num_ref_idx_l0_active - 1,
+    currSlice->reordering_of_pic_nums_idc_l0,
+    currSlice->abs_diff_pic_num_minus1_l0,
+    currSlice->long_term_pic_idx_l0);
+
+  if ( img->type == B_SLICE )
+  {
+    // LIST_1
+    num_ref = img->num_ref_idx_l1_active;
+
+    poc_ref_pic_reorder_frame(listX[LIST_1], num_ref,
+      currSlice->reordering_of_pic_nums_idc_l1,
+      currSlice->abs_diff_pic_num_minus1_l1,
+      currSlice->long_term_pic_idx_l1, LIST_1);
+    // reference picture reordering
+    reorder_ref_pic_list(listX[LIST_1], &listXsize[LIST_1],
+      img->num_ref_idx_l1_active - 1,
+      currSlice->reordering_of_pic_nums_idc_l1,
+      currSlice->abs_diff_pic_num_minus1_l1,
+      currSlice->long_term_pic_idx_l1);
+  }
+}
+
+
diff --git a/lencod_vc7.vcproj b/lencod_vc7.vcproj
index 7ffb13b..4f628cd 100644
--- a/lencod_vc7.vcproj
+++ b/lencod_vc7.vcproj
@@ -13,7 +13,7 @@
 	<Configurations>
 		<Configuration
 			Name="Debug|Win32"
-			OutputDirectory=".\lencod/Debug_vc7"
+			OutputDirectory=".\..\bin"
 			IntermediateDirectory=".\lencod/Debug_vc7"
 			ConfigurationType="1"
 			UseOfMFC="0"
@@ -75,7 +75,7 @@
 		</Configuration>
 		<Configuration
 			Name="Release|Win32"
-			OutputDirectory=".\lencod\Release_vc7"
+			OutputDirectory=".\..\bin"
 			IntermediateDirectory=".\lencod\Release_vc7"
 			ConfigurationType="1"
 			UseOfMFC="0"
@@ -157,6 +157,9 @@
 			<File
 				RelativePath=".\lencod\src\cabac.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\cconv_yuv2rgb.c">
+			</File>
 			<File
 				RelativePath=".\lencod\src\configfile.c">
 			</File>
@@ -167,7 +170,10 @@
 				RelativePath=".\lencod\src\context_ini.c">
 			</File>
 			<File
-				RelativePath=".\lencod\src\decoder.c">
+				RelativePath=".\lencod\src\errdo.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\errdo_mc_prediction.c">
 			</File>
 			<File
 				RelativePath=".\lencod\src\explicit_gop.c">
@@ -187,6 +193,18 @@
 			<File
 				RelativePath=".\lencod\src\img_chroma.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_ms_ssim.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_snr.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_ssim.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_distortion.c">
+			</File>
 			<File
 				RelativePath=".\lencod\src\img_luma.c">
 			</File>
@@ -277,6 +295,9 @@
 			<File
 				RelativePath=".\lencod\src\parsetcommon.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\q_around.c">
+			</File>
 			<File
 				RelativePath=".\lencod\src\q_matrix.c">
 			</File>
@@ -307,6 +328,18 @@
 			<File
 				RelativePath=".\lencod\src\quant8x8_trellis.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_around.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_normal.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_trellis.c">
+			</File>
 			<File
 				RelativePath=".\lencod\src\ratectl.c">
 			</File>
@@ -331,6 +364,9 @@
 			<File
 				RelativePath=".\lencod\src\refbuf.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\report.c">
+			</File>
 			<File
 				RelativePath=".\lencod\src\rtp.c">
 			</File>
@@ -355,6 +391,12 @@
 			<File
 				RelativePath=".\lencod\src\weighted_prediction.c">
 			</File>
+			<File
+				RelativePath=".\lencod\src\wp_lms.c">
+			</File>
+			<File
+				RelativePath=".\lencod\src\wp_mcprec.c">
+			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -371,6 +413,9 @@
 			<File
 				RelativePath=".\lencod\inc\cabac.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\cconv_yuv2rgb.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\configfile.h">
 			</File>
@@ -392,9 +437,21 @@
 			<File
 				RelativePath=".\lencod\inc\elements.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\enc_statistics.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\errdo.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\errdo_mc_prediction.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\explicit_gop.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\filehandle.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\fmo.h">
 			</File>
@@ -416,6 +473,21 @@
 			<File
 				RelativePath=".\lencod\inc\img_chroma.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_ms_ssim.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_snr.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_ssim.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_wpsnr.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_distortion.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\img_luma.h">
 			</File>
@@ -482,6 +554,9 @@
 			<File
 				RelativePath=".\lencod\inc\parsetcommon.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\q_around.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\q_matrix.h">
 			</File>
@@ -494,6 +569,9 @@
 			<File
 				RelativePath=".\lencod\inc\quant8x8.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\quantChroma.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\ratectl.h">
 			</File>
@@ -515,12 +593,18 @@
 			<File
 				RelativePath=".\lencod\inc\refbuf.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\report.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\rtp.h">
 			</File>
 			<File
 				RelativePath=".\lencod\inc\sei.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\slice.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\symbol.h">
 			</File>
@@ -530,6 +614,9 @@
 			<File
 				RelativePath=".\lencod\inc\transform8x8.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\transform_wavelet.h">
+			</File>
 			<File
 				RelativePath=".\lencod\inc\vlc.h">
 			</File>
@@ -539,6 +626,12 @@
 			<File
 				RelativePath=".\lencod\inc\wp.h">
 			</File>
+			<File
+				RelativePath=".\lencod\inc\wp_lms.h">
+			</File>
+			<File
+				RelativePath=".\lencod\inc\wp_mcprec.h">
+			</File>
 		</Filter>
 		<File
 			RelativePath="bin\encoder.cfg">
diff --git a/lencod_vc8.vcproj b/lencod_vc8.vcproj
index ad73ab8..f0bccd3 100644
--- a/lencod_vc8.vcproj
+++ b/lencod_vc8.vcproj
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8.00"
+	Version="8,00"
 	Name="lencod"
 	ProjectGUID="{9A39F1B7-3DFE-4263-8C02-8070F7D99AFA}"
+	RootNamespace="lencod"
 	>
 	<Platforms>
 		<Platform
@@ -224,6 +225,10 @@
 				RelativePath=".\lencod\src\cabac.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\cconv_yuv2rgb.c"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\src\configfile.c"
 				>
@@ -237,7 +242,11 @@
 				>
 			</File>
 			<File
-				RelativePath=".\lencod\src\decoder.c"
+				RelativePath=".\lencod\src\errdo.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\errdo_mc_prediction.c"
 				>
 			</File>
 			<File
@@ -264,6 +273,22 @@
 				RelativePath=".\lencod\src\img_chroma.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_ms_ssim.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_snr.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_dist_ssim.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\img_distortion.c"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\src\img_luma.c"
 				>
@@ -384,6 +409,10 @@
 				RelativePath=".\lencod\src\parsetcommon.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\q_around.c"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\src\q_matrix.c"
 				>
@@ -424,6 +453,22 @@
 				RelativePath=".\lencod\src\quant8x8_trellis.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_around.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_normal.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\quantChroma_trellis.c"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\src\ratectl.c"
 				>
@@ -456,6 +501,10 @@
 				RelativePath=".\lencod\src\refbuf.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\report.c"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\src\rtp.c"
 				>
@@ -488,6 +537,14 @@
 				RelativePath=".\lencod\src\weighted_prediction.c"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\src\wp_lms.c"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\src\wp_mcprec.c"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -509,6 +566,10 @@
 				RelativePath=".\lencod\inc\cabac.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\cconv_yuv2rgb.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\configfile.h"
 				>
@@ -537,10 +598,26 @@
 				RelativePath=".\lencod\inc\elements.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\enc_statistics.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\errdo.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\errdo_mc_prediction.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\explicit_gop.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\filehandle.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\fmo.h"
 				>
@@ -570,11 +647,27 @@
 				>
 			</File>
 			<File
-				RelativePath=".\lencod\inc\img_luma.h"
+				RelativePath=".\lencod\inc\img_dist_ms_ssim.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_snr.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_ssim.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_dist_wpsnr.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\img_distortion.h"
 				>
 			</File>
 			<File
-				RelativePath=".\lencod\inc\img_predblk.h"
+				RelativePath=".\lencod\inc\img_luma.h"
 				>
 			</File>
 			<File
@@ -661,6 +754,10 @@
 				RelativePath=".\lencod\inc\parsetcommon.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\q_around.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\q_matrix.h"
 				>
@@ -677,6 +774,10 @@
 				RelativePath=".\lencod\inc\quant8x8.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\quantChroma.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\ratectl.h"
 				>
@@ -705,6 +806,10 @@
 				RelativePath=".\lencod\inc\refbuf.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\report.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\rtp.h"
 				>
@@ -713,6 +818,10 @@
 				RelativePath=".\lencod\inc\sei.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\slice.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\symbol.h"
 				>
@@ -725,6 +834,10 @@
 				RelativePath=".\lencod\inc\transform8x8.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\transform_wavelet.h"
+				>
+			</File>
 			<File
 				RelativePath=".\lencod\inc\vlc.h"
 				>
@@ -737,6 +850,14 @@
 				RelativePath=".\lencod\inc\wp.h"
 				>
 			</File>
+			<File
+				RelativePath=".\lencod\inc\wp_lms.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lencod\inc\wp_mcprec.h"
+				>
+			</File>
 		</Filter>
 		<File
 			RelativePath="bin\encoder.cfg"
-- 
GitLab