SOURCE BUNDLE
Files: 152
Extensions: .c .cc .cpp .h .rc (case-insensitive)
Excluded directory names: opus
Directory and file symlinks are skipped.
Source bodies: decoded text; original line endings normalized to LF.
No source line numbers inserted. SHA-256 refers to original bytes.
Non-UTF-8 fallback: cp1250 (verify for your source tree).

FILE INDEX
0001 | CodecUtils/BitStreamBase.h | 3633 bytes | utf-8
0002 | CodecUtils/BitStreamBaseMSB.h | 3797 bytes | utf-8
0003 | CodecUtils/BitStreamReaderMSB.cpp | 4779 bytes | utf-8
0004 | CodecUtils/BitStreamReaderMSB.h | 4702 bytes | utf-8
0005 | CodecUtils/BitStreamWriter.h | 4293 bytes | utf-8
0006 | CodecUtils/BitStreamWriterMSB.cpp | 5610 bytes | utf-8
0007 | CodecUtils/BitStreamWriterMSB.h | 5378 bytes | utf-8
0008 | CodecUtils/BlockH264.cpp | 11320 bytes | utf-8
0009 | CodecUtils/BlockH264.h | 8677 bytes | utf-8
0010 | CodecUtils/CAVLCH264Impl.cpp | 26706 bytes | utf-8
0011 | CodecUtils/CAVLCH264Impl.h | 5775 bytes | utf-8
0012 | CodecUtils/CAVLCH264Impl2.cpp | 23422 bytes | utf-8
0013 | CodecUtils/CAVLCH264Impl2.h | 6051 bytes | utf-8
0014 | CodecUtils/CodecConfigurationUtil.h | 6181 bytes | utf-8
0015 | CodecUtils/CodecDistortionDef.h | 2556 bytes | utf-8
0016 | CodecUtils/CodecParameters.h | 3028 bytes | utf-8
0017 | CodecUtils/CodedBlkPatternH264VlcDecoder.cpp | 5057 bytes | utf-8
0018 | CodecUtils/CodedBlkPatternH264VlcDecoder.h | 3537 bytes | utf-8
0019 | CodecUtils/CodedBlkPatternH264VlcEncoder.cpp | 4898 bytes | utf-8
0020 | CodecUtils/CodedBlkPatternH264VlcEncoder.h | 3443 bytes | utf-8
0021 | CodecUtils/CodeFragmentForH264BlockLayerTest.cpp | 35987 bytes | utf-8
0022 | CodecUtils/CoeffTokenH264VlcDecoder.cpp | 40946 bytes | utf-8
0023 | CodecUtils/CoeffTokenH264VlcDecoder.h | 3942 bytes | utf-8
0024 | CodecUtils/CoeffTokenH264VlcEncoder.cpp | 9809 bytes | utf-8
0025 | CodecUtils/CoeffTokenH264VlcEncoder.h | 4302 bytes | utf-8
0026 | CodecUtils/ExpGolombSignedVlcDecoder.h | 3254 bytes | utf-8
0027 | CodecUtils/ExpGolombSignedVlcEncoder.h | 3176 bytes | utf-8
0028 | CodecUtils/ExpGolombTruncVlcDecoder.h | 3635 bytes | utf-8
0029 | CodecUtils/ExpGolombTruncVlcEncoder.h | 3487 bytes | utf-8
0030 | CodecUtils/ExpGolombUnsignedVlcDecoder.cpp | 3527 bytes | utf-8
0031 | CodecUtils/ExpGolombUnsignedVlcDecoder.h | 3079 bytes | utf-8
0032 | CodecUtils/ExpGolombUnsignedVlcEncoder.cpp | 4074 bytes | utf-8
0033 | CodecUtils/ExpGolombUnsignedVlcEncoder.h | 3408 bytes | utf-8
0034 | CodecUtils/FastForward4x4ITImpl1.cpp | 8288 bytes | utf-8
0035 | CodecUtils/FastForward4x4ITImpl1.h | 5360 bytes | utf-8
0036 | CodecUtils/FastForward4x4ITImpl2.cpp | 21471 bytes | utf-8
0037 | CodecUtils/FastForward4x4ITImpl2.h | 5373 bytes | utf-8
0038 | CodecUtils/FastForward4x4On16x16ITImpl1.cpp | 26933 bytes | utf-8
0039 | CodecUtils/FastForward4x4On16x16ITImpl1.h | 5458 bytes | utf-8
0040 | CodecUtils/FastForwardDC2x2ITImpl1.cpp | 7011 bytes | utf-8
0041 | CodecUtils/FastForwardDC2x2ITImpl1.h | 5041 bytes | utf-8
0042 | CodecUtils/FastForwardDC4x4ITImpl1.cpp | 8846 bytes | utf-8
0043 | CodecUtils/FastForwardDC4x4ITImpl1.h | 5065 bytes | utf-8
0044 | CodecUtils/FastInverse4x4ITImpl1.cpp | 9391 bytes | utf-8
0045 | CodecUtils/FastInverse4x4ITImpl1.h | 4700 bytes | utf-8
0046 | CodecUtils/FastInverse4x4On16x16ITImpl1.cpp | 14051 bytes | utf-8
0047 | CodecUtils/FastInverse4x4On16x16ITImpl1.h | 4823 bytes | utf-8
0048 | CodecUtils/FastInverseDC2x2ITImpl1.cpp | 7358 bytes | utf-8
0049 | CodecUtils/FastInverseDC2x2ITImpl1.h | 4683 bytes | utf-8
0050 | CodecUtils/FastInverseDC4x4ITImpl1.cpp | 8719 bytes | utf-8
0051 | CodecUtils/FastInverseDC4x4ITImpl1.h | 4744 bytes | utf-8
0052 | CodecUtils/H263MotionVectorPredictorImpl1.cpp | 5442 bytes | utf-8
0053 | CodecUtils/H263MotionVectorPredictorImpl1.h | 3800 bytes | utf-8
0054 | CodecUtils/H264BitStreamReader.cpp | 5311 bytes | utf-8
0055 | CodecUtils/H264BitStreamReader.h | 1195 bytes | utf-8
0056 | CodecUtils/H264MbImgCache.cpp | 7165 bytes | utf-8
0057 | CodecUtils/H264MbImgCache.h | 4538 bytes | utf-8
0058 | CodecUtils/H264MotionVectorPredictorImpl1.h | 4279 bytes | utf-8
0059 | CodecUtils/H264RawFileHandler.cpp | 3849 bytes | utf-8
0060 | CodecUtils/H264RawFileHandler.h | 2627 bytes | utf-8
0061 | CodecUtils/IBitStreamReader.h | 4400 bytes | utf-8
0062 | CodecUtils/IBitStreamWriter.h | 4898 bytes | utf-8
0063 | CodecUtils/ICodecInnerAccess.h | 4105 bytes | utf-8
0064 | CodecUtils/ICodecv2.h | 5930 bytes | utf-8
0065 | CodecUtils/IContextAwareRunLevelCodec.h | 4246 bytes | utf-8
0066 | CodecUtils/IForwardDct.h | 1572 bytes | utf-8
0067 | CodecUtils/IForwardTransform.h | 4926 bytes | utf-8
0068 | CodecUtils/IInverseTransform.h | 4465 bytes | utf-8
0069 | CodecUtils/IMotionCompensator.h | 5082 bytes | utf-8
0070 | CodecUtils/IMotionEstimator.h | 3845 bytes | utf-8
0071 | CodecUtils/IMotionVectorPredictor.h | 3555 bytes | utf-8
0072 | CodecUtils/IRateControl.h | 5422 bytes | utf-8
0073 | CodecUtils/IRunLengthCodec.h | 1829 bytes | utf-8
0074 | CodecUtils/IStreamHeaderReader.h | 3476 bytes | utf-8
0075 | CodecUtils/IVlcDecoder.h | 3953 bytes | utf-8
0076 | CodecUtils/IVlcEncoder.h | 3344 bytes | utf-8
0077 | CodecUtils/MacroBlockH264.cpp | 48377 bytes | utf-8
0078 | CodecUtils/MacroBlockH264.h | 19363 bytes | utf-8
0079 | CodecUtils/MotionCompensatorH264ImplMultires.cpp | 24343 bytes | utf-8
0080 | CodecUtils/MotionCompensatorH264ImplMultires.h | 5908 bytes | utf-8
0081 | CodecUtils/MotionCompensatorH264ImplStd.cpp | 24827 bytes | utf-8
0082 | CodecUtils/MotionCompensatorH264ImplStd.h | 6391 bytes | utf-8
0083 | CodecUtils/MotionEstimatorH263ImplMultiresCross.cpp | 43743 bytes | utf-8
0084 | CodecUtils/MotionEstimatorH263ImplMultiresCross.h | 8455 bytes | utf-8
0085 | CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.cpp | 49085 bytes | utf-8
0086 | CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.h | 8962 bytes | utf-8
0087 | CodecUtils/MotionEstimatorH264ImplCross.cpp | 43022 bytes | utf-8
0088 | CodecUtils/MotionEstimatorH264ImplCross.h | 9022 bytes | utf-8
0089 | CodecUtils/MotionEstimatorH264ImplFull.cpp | 37403 bytes | utf-8
0090 | CodecUtils/MotionEstimatorH264ImplFull.h | 7348 bytes | utf-8
0091 | CodecUtils/MotionEstimatorH264ImplMultires.cpp | 49981 bytes | utf-8
0092 | CodecUtils/MotionEstimatorH264ImplMultires.h | 8786 bytes | utf-8
0093 | CodecUtils/MotionEstimatorH264ImplMultiresCross.cpp | 53047 bytes | utf-8
0094 | CodecUtils/MotionEstimatorH264ImplMultiresCross.h | 8989 bytes | utf-8
0095 | CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.cpp | 83114 bytes | utf-8
0096 | CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.h | 12067 bytes | utf-8
0097 | CodecUtils/MotionEstimatorH264ImplTest.cpp | 41991 bytes | utf-8
0098 | CodecUtils/MotionEstimatorH264ImplTest.h | 7845 bytes | utf-8
0099 | CodecUtils/NalHeaderH264.cpp | 2724 bytes | utf-8
0100 | CodecUtils/NalHeaderH264.h | 3422 bytes | utf-8
0101 | CodecUtils/PicParamSetH264.cpp | 9736 bytes | utf-8
0102 | CodecUtils/PicParamSetH264.h | 5573 bytes | utf-8
0103 | CodecUtils/PrefixH264VlcDecoderImpl1.h | 3339 bytes | utf-8
0104 | CodecUtils/PrefixH264VlcEncoderImpl1.h | 3290 bytes | utf-8
0105 | CodecUtils/RateControlImpl1.cpp | 22058 bytes | utf-8
0106 | CodecUtils/RateControlImpl1.h | 9971 bytes | utf-8
0107 | CodecUtils/RateControlImplLog.cpp | 23366 bytes | utf-8
0108 | CodecUtils/RateControlImplLog.h | 10494 bytes | utf-8
0109 | CodecUtils/RateControlImplMultiModel.cpp | 11194 bytes | utf-8
0110 | CodecUtils/RateControlImplMultiModel.h | 5821 bytes | utf-8
0111 | CodecUtils/RateControlImplPow.cpp | 25048 bytes | utf-8
0112 | CodecUtils/RateControlImplPow.h | 11626 bytes | utf-8
0113 | CodecUtils/RateControlImplQuad.cpp | 21311 bytes | utf-8
0114 | CodecUtils/RateControlImplQuad.h | 11192 bytes | utf-8
0115 | CodecUtils/RawFileHandlerBase.cpp | 6057 bytes | utf-8
0116 | CodecUtils/RawFileHandlerBase.h | 3428 bytes | utf-8
0117 | CodecUtils/RunBeforeH264VlcDecoder.cpp | 10200 bytes | utf-8
0118 | CodecUtils/RunBeforeH264VlcDecoder.h | 3339 bytes | utf-8
0119 | CodecUtils/RunBeforeH264VlcEncoder.cpp | 5328 bytes | utf-8
0120 | CodecUtils/RunBeforeH264VlcEncoder.h | 3727 bytes | utf-8
0121 | CodecUtils/SeqParamSetH264.cpp | 12364 bytes | utf-8
0122 | CodecUtils/SeqParamSetH264.h | 6700 bytes | utf-8
0123 | CodecUtils/SliceHeaderH264.cpp | 5179 bytes | utf-8
0124 | CodecUtils/SliceHeaderH264.h | 6113 bytes | utf-8
0125 | CodecUtils/TotalZeros2x2H264VlcDecoder.cpp | 5149 bytes | utf-8
0126 | CodecUtils/TotalZeros2x2H264VlcDecoder.h | 3388 bytes | utf-8
0127 | CodecUtils/TotalZeros2x2H264VlcEncoder.cpp | 4224 bytes | utf-8
0128 | CodecUtils/TotalZeros2x2H264VlcEncoder.h | 3778 bytes | utf-8
0129 | CodecUtils/TotalZeros2x4H264VlcDecoder.cpp | 8256 bytes | utf-8
0130 | CodecUtils/TotalZeros2x4H264VlcDecoder.h | 3390 bytes | utf-8
0131 | CodecUtils/TotalZeros2x4H264VlcEncoder.cpp | 4733 bytes | utf-8
0132 | CodecUtils/TotalZeros2x4H264VlcEncoder.h | 3786 bytes | utf-8
0133 | CodecUtils/TotalZeros4x4H264VlcDecoder.cpp | 23743 bytes | utf-8
0134 | CodecUtils/TotalZeros4x4H264VlcDecoder.h | 3933 bytes | utf-8
0135 | CodecUtils/TotalZeros4x4H264VlcEncoder.cpp | 6613 bytes | utf-8
0136 | CodecUtils/TotalZeros4x4H264VlcEncoder.h | 3777 bytes | utf-8
0137 | CodecUtils/VectorStructList.cpp | 8003 bytes | utf-8
0138 | CodecUtils/VectorStructList.h | 4651 bytes | utf-8
0139 | CodecUtils/YuvRawFileHandler.cpp | 5945 bytes | utf-8
0140 | CodecUtils/YuvRawFileHandler.h | 3812 bytes | utf-8
0141 | H264v2/H264v2.cpp | 1779 bytes | utf-8
0142 | H264v2/H264v2.h | 2869 bytes | utf-8
0143 | H264v2/stdafx.cpp | 1262 bytes | utf-8
0144 | H264v2/stdafx.h | 1074 bytes | utf-8
0145 | H264v2Codec/H264v2Codec.cpp | 522405 bytes | utf-8
0146 | H264v2Codec/H264v2Codec.h | 31928 bytes | utf-8
0147 | H264v2Codec/H264v2CodecHeader.cpp | 5537 bytes | utf-8
0148 | H264v2Codec/H264v2CodecHeader.h | 4437 bytes | utf-8
0149 | H264v2Codec/new/H264v2Codec.cpp | 521485 bytes | utf-8
0150 | H264v2Codec/new/H264v2Codec.h | 31928 bytes | utf-8
0151 | H264v2Codec/old/H264v2Codec.cpp | 518186 bytes | utf-8
0152 | H264v2Codec/old/H264v2Codec.h | 31689 bytes | utf-8

========== BEGIN FILE: CodecUtils/BitStreamBase.h ==========
Bundle entry: 1
Original bytes: 3633
Original SHA-256: d9550788c4f2f1712ff394f91936bb11cc05381d972838f0c063823895aba89c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamBase

TAG						: BSB

FILE NAME			: BitStreamBase.h

DESCRIPTION		: A base class to contain a contiguous mem array to be bit accessible. The 
                mem is not owned by the class. Derived classes handle the reading and writing, 
								BitStreamReader and BitStreamWriter.

COPYRIGHT			:	(c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _BITSTREAMBASE_H
#define _BITSTREAMBASE_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BitStreamBase
{
public:
	BitStreamBase()	
		{_bitStream = NULL; _bitSize = 0; _bytePos = 0; _bitPos = 0; }
	virtual ~BitStreamBase()	{ }

	virtual void SetStream(void* stream, int bitSize)	
		{ _bitStream = (unsigned char *)stream; 
			_bitSize = bitSize; 
			_bytePos = 0; _bitPos = 0; 
		}//end SetStream.

  virtual void* GetStream(void) { return( (void *)_bitStream ); }

public:
	/// Interface implementation.
	virtual void Reset(void) 
		{ _bytePos = 0; _bitPos = 0; }

	virtual int Seek(int streamBitPos) 
		{ if(streamBitPos >= _bitSize) 
				return(0);
			_bytePos	= streamBitPos / 8; 
			_bitPos		= streamBitPos % 8; 
			return(1); 
		}//end Seek.

	virtual int		GetStreamBitPos(void)					{ return( (_bytePos << 3) +  _bitPos); }
	virtual int		GetStreamBytePos(void)				{ return(_bytePos); }
	virtual void	SetStreamBitSize(int bitSize) { _bitSize = bitSize; }
	virtual int		GetStreamBitSize(void)				{ return(_bitSize); }

protected:
	unsigned char*	_bitStream;		///< Reference to byte array.
	int							_bitSize;			///< Bits in stream.
	/// Current location.
	int							_bytePos;
	int							_bitPos;

};// end class BitStreamBase.

#endif	// _BITSTREAMBASE_H
========== END FILE: CodecUtils/BitStreamBase.h ==========

========== BEGIN FILE: CodecUtils/BitStreamBaseMSB.h ==========
Bundle entry: 2
Original bytes: 3797
Original SHA-256: 2568b93ba5ac664a40a22482253fc8beaeb292af5754dd0802dd2a1ec8c21163
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamBaseMSB

TAG						: BSMSB

FILE NAME			: BitStreamBaseMSB.h

DESCRIPTION		: A base class to contain a contiguous mem array to be
								bit accessible. The mem is not owned by the class. 
								Derived classes handle the reading and writing, 
								BitStreamReaderMSB and BitStreamWriterMSB.

COPYRIGHT			: (c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _BITSTREAMBASEMSB_H
#define _BITSTREAMBASEMSB_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BitStreamBaseMSB
{
public:
	BitStreamBaseMSB()	
		{_bitStream = NULL; _bitSize = 0; _bytePos = 0; _bitPos = 7; }
	virtual ~BitStreamBaseMSB()	{ }

	virtual void SetStream(void* stream, int bitSize)	
		{ _bitStream = (unsigned char *)stream; 
			_bitSize = bitSize; 
			_bytePos = 0; _bitPos = 7; 
		}//end SetStream.

  virtual void* GetStream(void) { return( (void *)_bitStream ); }

public:
	/// Interface implementation.
	virtual void Reset(void) 
		{ _bytePos = 0; _bitPos = 7; }

	virtual int Seek(int streamBitPos) 
		{ if(streamBitPos >= _bitSize) 
				return(0);
			_bytePos	= streamBitPos / 8; 
			_bitPos		= streamBitPos % 8; 
			return(1); 
		}//end Seek.

	virtual int		GetStreamBitPos(void)					{ return( (_bytePos << 3) +  _bitPos ); }
	virtual int		GetStreamBytePos(void)				{ return(_bytePos); }
	virtual void	SetStreamBitSize(int bitSize) { _bitSize = bitSize; }
	virtual int		GetStreamBitSize(void)				{ return(_bitSize); }
	virtual int		GetStreamBitsRemaining(void)	{ return(_bitSize - ((_bytePos << 3) +  (7 - _bitPos))); }

protected:
	unsigned char*	_bitStream;		///< Reference to byte array.
	int							_bitSize;			///< Bits in stream.
	/// Current location that acts like a cursor in the stream.
	int							_bytePos;
	int							_bitPos;

};// end class BitStreamBaseMSB.

#endif	// _BITSTREAMBASEMSB_H
========== END FILE: CodecUtils/BitStreamBaseMSB.h ==========

========== BEGIN FILE: CodecUtils/BitStreamReaderMSB.cpp ==========
Bundle entry: 3
Original bytes: 4779
Original SHA-256: b066427705c50375809b162783dd3a1bc512d2aed39c0a9580422eb4580b998b
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamReaderMSB

TAG						: BSRMSB

FILE NAME			: BitStreamReaderMSB.cpp

DESCRIPTION		: A bit stream reader implementation of the BitStreamBase
								base class with the first bit as the MSB of the byte. 
								Add the functionality to do the reading.
									BitStreamReaderMSB* pBsr = new BitStreamReaderMSB();
									pBsr->SetStream((void *)pStream, (streamLen * sizeof(pStream[0]) * 8));
									pBsr->Read(5, codeWord);
									.
									.
									delete pBsr;

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "BitStreamReaderMSB.h"

BitStreamReaderMSB::BitStreamReaderMSB()
{
}//end constructor.

BitStreamReaderMSB::~BitStreamReaderMSB()
{
}//end destructor.

/** Read a single bit.
Read from the current bit position in the stream.
@return			: The bit [0,1].
*/
int BitStreamReaderMSB::Read(void)
{
  // Strip out the bit. 
  int codeBit = (int)(_bitStream[_bytePos] >> _bitPos) & 1;

  // Point to next available bit.
  if(_bitPos > 0)
		_bitPos--;
	else
  {
    _bitPos = 7;
    _bytePos++;
  }//end else...

  return(codeBit);
}//end Read.

/** Read bits from the stream.
Read multiple bits from the most significant bit downwards
from the current stream position.
@param numBits	: No. of bits to read.
@return					: The code.
*/
int BitStreamReaderMSB::Read(int numBits)
{
  int pos = _bitPos;
  int b		= 0;

  for(int i = numBits; i > 0; i--)
  {
    // Strip out the next bit and update in the bit position i.
    if((_bitStream[_bytePos] >> pos) & 1)
      b = (int)(b | (1 << (i-1)));	// bit=1
    else
      b = (int)(b & ~(1 << (i-1)));	// bit=0

    // Point to next available bit.
    if(pos > 0)
      pos--;
		else
    {
      pos = 7;
      _bytePos++;
    }//end else...
  }//end for i...

  // Update the global next bit position.
  _bitPos = pos;

  // Output the result.
  return(b);
}//end Read.

/** Peek bits in the stream.
Read multiple bits from the most significant bit downwards
from the specified stream position without disturbing the
current stream position.
@param bitLoc		: Bit pos in stream.
@param numBits	: No. of bits to read.
@return					: The code.
*/
int BitStreamReaderMSB::Peek(int bitLoc, int numBits)
{
  int bytePos = bitLoc / 8;
  int bitPos	= bitLoc % 8;
  int b				= 0;

  for(int i = numBits; i > 0; i--)
  {
    // Strip out the next bit and update in the bit position i.
    if((_bitStream[bytePos] >> bitPos) & 1)
      b = (int)(b | (1 << (i-1)));	// bit=1
    else
      b = (int)(b & ~(1 << (i-1)));	// bit=0

    // Point to next available bit.
    if(bitPos > 0)
      bitPos--;
		else
    {
      bitPos = 7;
      bytePos++;
    }//end else...
  }//end for i...

  // Output the result.
  return(b);
}//end Peek.



========== END FILE: CodecUtils/BitStreamReaderMSB.cpp ==========

========== BEGIN FILE: CodecUtils/BitStreamReaderMSB.h ==========
Bundle entry: 4
Original bytes: 4702
Original SHA-256: 564fdf41db350e2514d55413836f2430b507fded14d8c95007079ee4d3b6c42b
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamReaderMSB

TAG						: BSRMSB

FILE NAME			: BitStreamReaderMSB.h

DESCRIPTION		: A bit stream reader implementation of the BitStreamBase
								base class with the first bit as the MSB of the byte. 
								Add the functionality to do the bit reading.
								Basic operation:
									BitStreamReaderMSB* pBsr = new BitStreamReaderMSB();
									pBsr->SetStream((void *)pStream, (streamLen * sizeof(pStream[0]) * 8));
									pBsr->Read(5, codeWord);
									.
									.
									delete pBsr;

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _BITSTREAMREADERMSB_H
#define _BITSTREAMREADERMSB_H

#pragma once

#include "BitStreamBaseMSB.h"
#include "IBitStreamReader.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BitStreamReaderMSB : public BitStreamBaseMSB, public IBitStreamReader
{
public:
	BitStreamReaderMSB();
	virtual ~BitStreamReaderMSB();

/// Interface implementation.
public:
	/** Read a single bit.
	Read from the current bit position in the stream.
	@param val	: Bit value to write.
	@return			: The bit [0,1].
	*/
	int Read(void);

	/** Read bits from the stream.
	Read multiple bits from the most significant bit downwards
	from the current stream position.
	@param numBits	: No. of bits to read.
	@return					: The code.
	*/
	int Read(int numBits);

	/** Peek bits in the stream.
	Read multiple bits from the most significant bit downwards
	from the specified stream position without disturbing the
	current stream position.
	@param bitLoc		: Bit pos in stream.
	@param numBits	: No. of bits to read.
	@return					: The code.
	*/
	int Peek(int bitLoc, int numBits);

///	Use base class implementations.
public:
	void SetStream(void* stream, int bitSize) { BitStreamBaseMSB::SetStream(stream, bitSize); }	

	void* GetStream(void) { return(BitStreamBaseMSB::GetStream()); }	

	void Reset(void) { BitStreamBaseMSB::Reset(); }

	int Seek(int streamBitPos) { return(BitStreamBaseMSB::Seek(streamBitPos)); }

	int GetStreamBitPos(void) { return(BitStreamBaseMSB::GetStreamBitPos()); }

	int GetStreamBytePos(void) { return(BitStreamBaseMSB::GetStreamBytePos()); }

	void SetStreamBitSize(int bitSize) { BitStreamBaseMSB::SetStreamBitSize(bitSize); }

	int GetStreamBitSize(void) { return(BitStreamBaseMSB::GetStreamBitSize()); }

	int GetStreamBitsRemaining(void) { return(BitStreamBaseMSB::GetStreamBitsRemaining()); }

  void Copy(IBitStreamReader* pFrom)
  {
    _bitStream  = (unsigned char*)pFrom->GetStream();
    _bitSize    = pFrom->GetStreamBitSize();
    _bytePos    = pFrom->GetStreamBytePos();
    _bitPos     = pFrom->GetStreamBitPos() % 8;
  }//end Copy.

};// end class BitStreamReaderMSB.

#endif	// _BITSTREAMREADERMSB_H
========== END FILE: CodecUtils/BitStreamReaderMSB.h ==========

========== BEGIN FILE: CodecUtils/BitStreamWriter.h ==========
Bundle entry: 5
Original bytes: 4293
Original SHA-256: 80ad79ff0b945ddbcfca53841b61384359f21acb8b4202ca33e967c78fdd69b2
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamWriter

TAG						: BSW

FILE NAME			: BitStreamWriter.h

DESCRIPTION		: A bit stream writer implementation of the BitStreamBase
								base class. Add the functionality to do the bit writing.
								Basic operation:
									BitStreamWriter* pBsr= new BitStreamWriter();
									pBsr->SetStream((void *)pStream, (streamLen * sizeof(pStream[0]) * 8));
									pBsr->Write(5, codeWord);
									.
									.
									delete pBsr;

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _BITSTREAMWRITER_H
#define _BITSTREAMWRITER_H

#pragma once

#include "BitStreamBase.h"
#include "IBitStreamWriter.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BitStreamWriter : public BitStreamBase, public IBitStreamWriter
{
public:
	BitStreamWriter();
	virtual ~BitStreamWriter();

/// Interface implementation.
public:
	/** Write a single bit.
	Write to the current bit position into the stream.
	@param val	: Bit value to write.
	@return			: none.
	*/
	void Write(int val);

	/** Write bits to the stream.
	Write multiple bits from the least significant bit upwards
	into the current stream position.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	void Write(int numBits, int val);
  void Write(int numBits, int valH, int ValL) { }

	/** Poke bits to the stream.
	Write multiple bits from the least significant bit upwards
	into the specified stream position without disturbing the
	current stream position.
	@param bitLoc		: Bit pos in stream.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	void Poke(int bitLoc, int numBits, int val);

///	Use base class implementations.
public:
	void SetStream(void* stream, int bitSize) { BitStreamBase::SetStream(stream, bitSize); }	

	void* GetStream(void) { return(BitStreamBase::GetStream()); }	

	void Reset(void) { BitStreamBase::Reset(); }

	int Seek(int streamBitPos) { return(BitStreamBase::Seek(streamBitPos)); }

	int GetStreamBitPos(void) { return(BitStreamBase::GetStreamBitPos()); }

	int GetStreamBytePos(void) { return(BitStreamBase::GetStreamBytePos()); }

	void SetStreamBitSize(int bitSize) { BitStreamBase::SetStreamBitSize(bitSize); }

};// end class BitStreamWriter.

#endif	// _BITSTREAMWRITER_H
========== END FILE: CodecUtils/BitStreamWriter.h ==========

========== BEGIN FILE: CodecUtils/BitStreamWriterMSB.cpp ==========
Bundle entry: 6
Original bytes: 5610
Original SHA-256: 86e356da02c70877795bdf4faaee8a9416a2b2eab7173efe4ad2fc7e43087886
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamWriterMSB

TAG						: BSWMSB

FILE NAME			: BitStreamWriterMSB.cpp

DESCRIPTION		: A bit stream writer implementation of the BitStreamBase
								base class with the first bit as the MSB of the byte. 
								Add the functionality to do the writing.
								Basic operation:
									BitStreamWriterMSB* pBsr= new BitStreamWriterMSB();
									pBsr->SetStream((void *)pStream, (streamLen * sizeof(pStream[0]) * 8));
									pBsr->Write(5, codeWord);
									.
									.
									delete pBsr;

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "BitStreamWriterMSB.h"

BitStreamWriterMSB::BitStreamWriterMSB()
{
}//end constructor.

BitStreamWriterMSB::~BitStreamWriterMSB()
{
}//end destructor.

/** Write a single bit.
Write to the current bit position in the stream.
@param val	: Bit value to write.
@return			: none.
*/
void BitStreamWriterMSB::Write(int val)
{
  // Strip out the bit of the input and write it to the bit position.
  if(val & 1)
		_bitStream[_bytePos] = _bitStream[_bytePos] | (1 << _bitPos);
  else
    _bitStream[_bytePos] = _bitStream[_bytePos] & ~(1 << _bitPos);

  // Point to next available bit.
  if(_bitPos > 0)
    _bitPos--;
	else
  {
		// Update the bit stream location.
    _bitPos = 7;
    _bytePos++;
  }//end else...
}//end Write.

/** Write bits to the stream.
Write multiple bits from the most significant bit downwards
into the current stream position.
@param numBits	: No. of bits to write.
@param val			: Bit value to write.
@return					: none.
*/
void BitStreamWriterMSB::Write(int numBits, int val)
{
  int pos = _bitPos;
  int b		= val;
	unsigned char cachedByte = _bitStream[_bytePos];

	unsigned int inMask = 1 << (numBits - 1);	// Align a 1 on the MSB of the input val.
  for(int i = numBits; i > 0; i--)
  {
    // Strip out the bit of the input from the MSB valid bit downwards 
		// and write it to bit position pos.
    if(b & inMask)
			cachedByte = cachedByte | (1 << pos);
    else
      cachedByte = cachedByte & ~(1 << pos);

    // Point to next available bit.
    if(pos > 0)
			pos--;
		else
    {
			// Update the bit stream from cache.
			_bitStream[_bytePos] = cachedByte;
      pos = 7;
      _bytePos++;
			// Renew the cache.
			cachedByte = _bitStream[_bytePos];
    }//end else...

    // Update the input mask to the next MSB.
    inMask = inMask >> 1;
  }//end for i...

	// Flush the cache.
	_bitStream[_bytePos] = cachedByte;
  // Update the global next bit position.
  _bitPos = pos;
}//end Write.

/** Poke bits to the stream.
Write multiple bits from the most significant bit downwards
into the specified stream position without disturbing the
current stream position.
@param bitLoc		: Bit pos in stream.
@param numBits	: No. of bits to write.
@param val			: Bit value to write.
@return					: none.
*/
void BitStreamWriterMSB::Poke(int bitLoc, int numBits, int val)
{
	int bytePos = bitLoc / 8;
  int bitPos	= bitLoc % 8;
  int b				= val;

	int inMask = 1 << (numBits - 1);	// Align a 1 on the MSB of the input val.
  for(int i = numBits; i > 0; i--)
  {
    // Strip out the LSB bit of the input and write it to bit position.
    if(b & inMask)
			_bitStream[bytePos] = _bitStream[bytePos] | (1 << bitPos);
    else
      _bitStream[bytePos] = _bitStream[bytePos] & ~(1 << bitPos);

    // Point to next available bit.
    if(bitPos > 0)
			bitPos--;
		else
    {
      bitPos = 7;
      bytePos++;
    }//end else...

    // Update the input mask to the next MSB.
    inMask = inMask >> 1;
  }//end for i...

}//end Poke.


========== END FILE: CodecUtils/BitStreamWriterMSB.cpp ==========

========== BEGIN FILE: CodecUtils/BitStreamWriterMSB.h ==========
Bundle entry: 7
Original bytes: 5378
Original SHA-256: ee63cd236aff5e8bde68fdb660b36831f3315b38707c8bc3590a41488a0b9dba
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BitStreamWriterMSB

TAG						: BSWMSB

FILE NAME			: BitStreamWriterMSB.h

DESCRIPTION		: A bit stream writer implementation of the extending the
								BitStreamBase	base class with the first bit as the MSB 
								of the byte. Implements a IBitStreamWriter interface. 
								Add the functionality to do the bit writing.
								Basic operation:
									BitStreamWriterMSB* pBsr= new BitStreamWriterMSB();
									pBsr->SetStream((void *)pStream, (streamLen * sizeof(pStream[0]) * 8));
									pBsr->Write(5, codeWord);
									.
									.
									delete pBsr;

COPYRIGHT			: (c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _BITSTREAMWRITERMSB_H
#define _BITSTREAMWRITERMSB_H

#pragma once

#include "BitStreamBaseMSB.h"
#include "IBitStreamWriter.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BitStreamWriterMSB : public BitStreamBaseMSB, public IBitStreamWriter
{
public:
	BitStreamWriterMSB();
	virtual ~BitStreamWriterMSB();

// Interface implementation.
public:
	/** Write a single bit.
	Write to the current bit position into the stream.
	@param val	: Bit value to write.
	@return			: none.
	*/
	void Write(int val);

	/** Write bits to the stream 32 bits.
	Write multiple bits from the most significant bit downwards
	into the current stream position.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	void Write(int numBits, int val);

	/** Write bits to the stream - 64 bits.
	Write multiple bits into the current stream position for 64 bit values.
	@param numBits	: No. of bits to write.
	@param valH			: Upper 32 bit value to write.
	@param valL			: Lower 32 bit value to write.
	@return					: none.
	*/
	void Write(int numBits, int valH, int valL)
  {
    if(numBits > 32)
    {
      Write(numBits-32, valH);  ///< MSBs first.
      Write(32, valL);
    }//end if numBits...
    else
      Write(numBits, valL);
  }//end Write.

	/** Poke bits to the stream.
	Write multiple bits from the most significant bit downwards
	into the specified stream position without disturbing the
	current stream position.
	@param bitLoc		: Bit pos in stream.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	void Poke(int bitLoc, int numBits, int val);

///	Use base class implementations.
public:
	void SetStream(void* stream, int bitSize) { BitStreamBaseMSB::SetStream(stream, bitSize); }	

	void* GetStream(void) { return(BitStreamBaseMSB::GetStream()); }	

	void Reset(void) { BitStreamBaseMSB::Reset(); }

	int Seek(int streamBitPos) { return(BitStreamBaseMSB::Seek(streamBitPos)); }

	int GetStreamBitPos(void) { return(BitStreamBaseMSB::GetStreamBitPos()); }

	int GetStreamBytePos(void) { return(BitStreamBaseMSB::GetStreamBytePos()); }

	void SetStreamBitSize(int bitSize) { BitStreamBaseMSB::SetStreamBitSize(bitSize); }

	int GetStreamBitSize(void) { return(BitStreamBaseMSB::GetStreamBitSize()); }

	int GetStreamBitsRemaining(void) { return(BitStreamBaseMSB::GetStreamBitsRemaining()); }

  void Copy(IBitStreamWriter* pFrom)
  {
    _bitStream  = (unsigned char*)pFrom->GetStream();
    _bitSize    = pFrom->GetStreamBitSize();
    _bytePos    = pFrom->GetStreamBytePos();
    _bitPos     = pFrom->GetStreamBitPos() % 8;
  }//end Copy.

};// end class BitStreamWriterMSB.

#endif	// _BITSTREAMWRITERMSB_H
========== END FILE: CodecUtils/BitStreamWriterMSB.h ==========

========== BEGIN FILE: CodecUtils/BlockH264.cpp ==========
Bundle entry: 8
Original bytes: 11320
Original SHA-256: 8a25c8a5e03a3725461f079a3a0f93b5ad02d9ca59fac3a880ab5e234655a8db
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BlockH264

TAG						: BH264

FILE NAME			: BlockH264.cpp

DESCRIPTION		: A class to hold H.264 block data and define all block
								operations. This is a container class on which to "hang"
								the processing functions.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#include <string.h>
#endif

#include <memory.h>

#include "BlockH264.h"

#include "OverlayMem2Dv2.h"
#include "IForwardTransform.h"
#include "IInverseTransform.h"
#include "IContextAwareRunLevelCodec.h"
#include "IBitStreamReader.h"
#include "IBitStreamWriter.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
BlockH264::BlockH264(void)
{
	/// Dangerous to alloc mem in the constructor. Should be 2 phase 
	/// construction. Use ready flag to check against.
	_ready			= 0;
	_coded			= 0;
	_numCoeffs	= 0;
	_width			= 4;	///< Default to a 4x4 block.
	_height			= 4;
	_length			= 16;
	_colour			= LUM;
	_dcFlag			= 1;

	/// Location aware members.
	_offX				= 0;		///< Block coord offset from top left of macroblock.
	_offY				= 0;
	/// Neighborhood access for determining context-aware variables.
	_blkAbove		= NULL;
	_blkLeft		= NULL;

	/// The 4x4 block mem.
	_pBlk = NULL;
	_pBlk = new short[_length];

	/// The block overlay.
	_blk = NULL;
	_blk = new OverlayMem2Dv2(_pBlk, _width, _height, _width, _height);

	if( (_pBlk != NULL)&&(_blk != NULL) )
		_ready = 1;

}//end constructor.

BlockH264::BlockH264(int width, int height)
{
	/// Dangerous to alloc mem in the constructor. Should be 2 phase 
	/// construction. Use ready flag to check against.
	_ready			= 0;
	_coded			= 0;
	_numCoeffs	= 0;
	_width			= width;
	_height			= height;
	_length			= width * height;

	/// Location aware members.
	_offX				= 0;
	_offY				= 0;
	_blkAbove		= NULL;
	_blkLeft		= NULL;

	/// The width x height block mem.
	_pBlk = NULL;
	_pBlk = new short[_length];

	/// The block overlay.
	_blk = NULL;
	_blk = new OverlayMem2Dv2(_pBlk, _width, _height, _width, _height);

	if( (_pBlk != NULL)&&(_blk != NULL) )
		_ready = 1;

}//end constructor.

BlockH264::~BlockH264(void)
{
	DeleteMem();
}//end destructor.

void BlockH264::ForwardTransform(IForwardTransform* pIT) 
{ 
  pIT->Transform(_pBlk); 
}

void BlockH264::InverseTransform(IInverseTransform* pIIT) 
{ 
  pIIT->InverseTransform(_pBlk); 
}

void BlockH264::Quantise(IForwardTransform* pQ) 
{ 
  pQ->Transform(_pBlk); 
}

void BlockH264::InverseQuantise(IInverseTransform* pQ) 
{ 
  pQ->InverseTransform(_pBlk); 
}

void BlockH264::DeleteMem(void)
{
	if(_blk != NULL)
		delete _blk;
	_blk = NULL;

	if(_pBlk != NULL)
		delete[] _pBlk;
	_pBlk = NULL;

	_ready = 0;
}//end DeleteMem.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Quantisation and inverse quantisation of block coeffs.
The transform classes are assumed to implement scaling and quantisation on
the block as a mode setting. Therefore the current mode is stored and replaced
after the quantisation only process.
@param pQ	: A forward transform object to use.
@param q	: Quantisation parameter.
@return		: None.
*/
void BlockH264::Quantise(IForwardTransform* pQ, int q)
{ 
	int mode = pQ->GetMode();					///< Store current mode. 
	pQ->SetParameter(pQ->QUANT_ID,q);	///< Set quant param.
	pQ->SetMode(pQ->QuantOnly);				///< Exclude the integer transform.
	pQ->Transform(_pBlk);							///< Do the quant. 
	pQ->SetMode(mode);								///< Restore previous mode.
}//end Quantise.

void BlockH264::InverseQuantise(IInverseTransform* pQ, int q)
{ 
	int mode = pQ->GetMode();					///< Store current mode. 
	pQ->SetParameter(pQ->QUANT_ID,q);	///< Set quant param.
	pQ->SetMode(pQ->QuantOnly);				///< Exclude the integer transform.
	pQ->InverseTransform(_pBlk);			///< Do the inverse quant. 
	pQ->SetMode(mode);								///< Restore previous mode.
}//end InverseQuantise.

int BlockH264::RleEncode(IContextAwareRunLevelCodec* rlc, IBitStreamWriter* pBsw) {
  int numBits = rlc->Encode((void *)_pBlk, (void *)pBsw);
  _numCoeffs = rlc->GetParameter(rlc->NUM_TOT_COEFF_ID);
  return(numBits);
}

int BlockH264::RleDecode(IContextAwareRunLevelCodec* rlc, IBitStreamReader* pBsr) {
  int numBits = rlc->Decode((void *)pBsr, (void *)_pBlk);
  _numCoeffs = rlc->GetParameter(rlc->NUM_TOT_COEFF_ID);
  return(numBits);
}

/** Copy from another block.
Match the mem size and copy all members and block
data.
@param pBlk	: Block to copy from.
@return			: 1/0 = success/failure.
*/
int BlockH264::CopyBlock(BlockH264* pBlk)
{
	/// Set memory members.
	SetDim(pBlk->GetWidth(), pBlk->GetHeight());
	if(!_ready)
		return(0);
	pBlk->Copy( (void *)_pBlk );

	/// Private members.
	SetCoded(pBlk->IsCoded());
	SetNumCoeffs(pBlk->GetNumCoeffs());
	SetColour(pBlk->GetColour());
	SetDcFlag(pBlk->IsDc());
	/// Public members.
	_offX			= pBlk->_offX;
	_offY			= pBlk->_offY;
	_blkAbove	= pBlk->_blkAbove;
	_blkLeft	= pBlk->_blkLeft;

	return(1);
}//end CopyBlock.

/** Get the number of neighbourhood coeffs
Assume that all the neighbourhood references above and left have
been pre-defined before calling this method. Find the average if
both neighbours exist or return the count for either if the other 
does not exist.
@param pBlk		: Block to operate on.
@return				: Number of neighbourhood coeffs.
*/
int BlockH264::GetNumNeighbourCoeffs(BlockH264* pBlk)
{
	int neighCoeffs = 0;

	if(pBlk->_blkAbove != NULL)
		neighCoeffs += (pBlk->_blkAbove)->GetNumCoeffs();
	if(pBlk->_blkLeft != NULL)
		neighCoeffs += (pBlk->_blkLeft)->GetNumCoeffs();
	if((pBlk->_blkAbove != NULL)&&(pBlk->_blkLeft != NULL))
		neighCoeffs = (neighCoeffs + 1)/2;

	return(neighCoeffs);
}//end GetNumNeighbourCoeffs.

/** Check for content equality with another block.
Only check the members that relates to the state of the block
and its contents not its position.
@param me		: This block.
@param pBlk	: Block to test against.
@return			: 1/0 = equals/not equals.
*/
int BlockH264::EqualsProxy(BlockH264* me, BlockH264* pBlk)
{
	for(int i = 0; i < me->_length; i++)
	{
		if(me->_pBlk[i] != pBlk->_pBlk[i])
			return(0);
	}//end for i...

	if( (me->_coded != pBlk->_coded) ||
			(me->_width != pBlk->_width) ||
			(me->_height != pBlk->_height) ||
			(me->_length != pBlk->_length) ||
			(me->_colour != pBlk->_colour) ||
			(me->_dcFlag != pBlk->_dcFlag) ||
			(me->_ready != pBlk->_ready) ||
			(me->_numCoeffs != pBlk->_numCoeffs) )
		return(0);

	return(1);
}//end Equals.

/*
---------------------------------------------------------------------------
	Access Methods.
---------------------------------------------------------------------------
*/

/** Set the block dimensions.
This should not be called often and typically after instantiation. The width
and height of the block are set and the memory is adjusted for these new
sizes. A call to Ready() will check the successful mem alloc.
@param	width		: Block width.
@param	height	: Block height.
@return					: None.
*/
void BlockH264::SetDim(int width, int height)
{
	/// No need to repeat mem allocation.
	if( (_width != width)||(_height != height) )
	{
		DeleteMem();		///< Clean the house out first.
		_width = width; 
		_height = height; 
		_length = width*height;
		/// The block mem.
		_pBlk = NULL;
		_pBlk = new short[_length];
		/// The block overlay.
		_blk = NULL;
		_blk = new OverlayMem2Dv2(_pBlk, _width, _height, _width, _height);
		/// Household check.
		if( (_pBlk != NULL)&&(_blk != NULL) )
			_ready = 1;
	}//end if width...
}//end SetDim.

/** Copy from the blk into the buffer.
No checking is done for overflow and is assumed to 
be _length * short in size.
@param buff	: Buffer to copy into.
@return			: none.
*/
void BlockH264::Copy(void* buff)
{
	if(buff != NULL)
  	memcpy(buff, (const void *)_pBlk, _length * sizeof(short));
}//end Copy.

/** Copy a row from the blk into the buffer.
No checking is done for overflow and is assumed to 
be _length * short in size.
@param row	: Block row to copy from.
@param buff	: Buffer to copy into.
@return			: none.
*/
void BlockH264::CopyRow(int row, void* buff)
{
	if(buff == NULL)
		return;
	short* pSrc = &(_pBlk[_width*row]);
	memcpy(buff, (const void *)pSrc, _width * sizeof(short));
}//end CopyRow.

/** Copy a col from the blk into the buffer.
No checking is done for overflow and is assumed to 
be _length * short in size.
@param col	: Block col to copy from.
@param buff	: Buffer to copy into.
@return			: none.
*/
void BlockH264::CopyCol(int col, void* buff)
{
	if(buff == NULL)
		return;
	short*	pDst	= (short *)buff;
	int			i			= col;
	for(int j = 0; j < _height; j++, i += _width)
		pDst[j] = _pBlk[i];
}//end CopyCol.

/** Zero all elements in the block.
No checking is done for overflow and is assumed to 
be _length * short in size.
@return			: none.
*/
void BlockH264::Zero(void)
{
	short* pSrc = &(_pBlk[0]);
	memset((void *)pSrc, 0, _length * sizeof(short));
}//end Zero.

========== END FILE: CodecUtils/BlockH264.cpp ==========

========== BEGIN FILE: CodecUtils/BlockH264.h ==========
Bundle entry: 9
Original bytes: 8677
Original SHA-256: b9df62381e0616b340978e6c54b120b0292239807ae157112aa2929b4a222106
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: BlockH264

TAG						: BH264

FILE NAME			: BlockH264.h

DESCRIPTION		: A class to hold H.264 block data and define all block
								operations. This is a container class on which to "hang"
								the processing functions.

COPYRIGHT			:	(c)CSIR 2007-2016 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _BLOCKH264_H
#define _BLOCKH264_H

#pragma once

// forward declarations
class OverlayMem2Dv2;
class IForwardTransform;
class IInverseTransform;
class IContextAwareRunLevelCodec;
class IBitStreamReader;
class IBitStreamWriter;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class BlockH264
{
public:
	BlockH264(void);
	BlockH264(int width, int height);
	virtual ~BlockH264(void);
	int			Ready(void) { return(_ready); }

/// Block operations.
public:
	/** Forward and inverse integer transform.
	The calling function is responsible to set the modes and parameters of the
	transform that might include the quantisation or intra/inter switch. The 
	context of the call is outside the scope of this class.
	@param	pIT	: The transform to operate on this block.
	@return			: None.
	*/
  void ForwardTransform(IForwardTransform* pIT);
  void InverseTransform(IInverseTransform* pIIT);

	/** Quantisation and inverse quantisation of block coeffs.
	The transform classes are assumed to implement scaling and quantisation on
	the block as a mode setting. Therefore the current mode is stored and replaced
	after the quantisation only process.
	@param pQ	: A forward transform object to use.
	@param q	: Quantisation parameter.
	@return		: None.
	*/
	virtual void Quantise(IForwardTransform* pQ, int q);
	virtual void InverseQuantise(IInverseTransform* pQ, int q);
	/** Simple quantisation and inverse quantisation of block coeffs.
	Assume the transform mode is set to QuantOnly and the quant parameter is set
	prior to calling these simplified methods. These are used for cases where the 
	quant parameter is const over multiple calls.
	@param pQ	: A forward transform object to use.
	@return		: None.
	*/
  virtual void Quantise(IForwardTransform* pQ);
  virtual void InverseQuantise(IInverseTransform* pQ);

	/** Run-Level encode and decode to and from a stream.
	The set up of the run-level codec must be done outside of
	the scope of this block.
	@param rlc		: The run-level codec to use.
	@param pBsw/r	: Stream reference to use.
	@return				: No. of bits consumed.
	*/
	int RleEncode(IContextAwareRunLevelCodec* rlc, IBitStreamWriter* pBsw); 
  int RleDecode(IContextAwareRunLevelCodec* rlc, IBitStreamReader* pBsr);
	/** Is the block all zeros.
	Included is the setting of the _coded flag to indicate the
	existence of non-zero values.
	@return : 1 = all zeros, 0 = non-zeros exist.
	*/
	int IsZero(void)
	{
    for(int i = 0; i < _length; i++)
    {
      if(_pBlk[i++] || _pBlk[i++] || _pBlk[i++] || _pBlk[i])
      {
				_coded = 1;
				return(0);	///< Early exit.
      }//end if _pBlk...
    }//end for i...

		_coded = 0;
		return(1);
	}//end IsZero.
	/// Version without setting _coded flag.
	int IsZero2(void)
	{
    for(int i = 0; i < _length; i++)
    {
      if(_pBlk[i++] || _pBlk[i++] || _pBlk[i++] || _pBlk[i])
				return(0);	///< Early exit.
    }//end for i...

		return(1);
	}//end IsZero2.

	/** Copy from another block.
	Match the mem size and copy all members and block
	data.
	@param pBlk	: Block to copy from.
	@return			: 1/0 = success/failure.
	*/
	int CopyBlock(BlockH264* pBlk);

/// Interface implementation.
public:
	/** Get the number of neighbourhood coeffs
	Assume that all the neighbourhood references above and left have
	been pre-defined before calling this method. Find the average if
	both neighbours exist or return the count for either if the other 
	does not exist.
	@param pBlk		: Block to operate on.
	@return				: Number of neighbourhood coeffs.
	*/
	static int GetNumNeighbourCoeffs(BlockH264* pBlk);

	/** Check for content equality with another block.
	Only check the members that relates to the state of the block
	and its contents not its position.
	@param pBlk	: Block to test against.
	@return			: 1/0 = equals/not equals.
	*/
	int Equals(BlockH264* pBlk) { return(EqualsProxy(this, pBlk)); }
	static int EqualsProxy(BlockH264* me, BlockH264* pBlk);

/// Member access.
public:
	OverlayMem2Dv2*	GetBlkOverlay(void)								{ return(_blk); }
	short*					GetBlk(void)											{ return(_pBlk); }
	int							IsCoded(void)											{ return(_coded); }
	void						SetCoded(int coded)								{ _coded = coded; }
	int							GetDC(void)												{ return(_pBlk[0]); }
	void						SetDC(int dc)											{ _pBlk[0] = (short)dc; }
	void						SetDim(int width, int height);
	int							GetWidth(void)										{ return(_width); }
	int							GetHeight(void)										{ return(_height); }
	void						SetNumCoeffs(int numCoeffs)				{ _numCoeffs = numCoeffs; }
	int							GetNumCoeffs(void)								{ return(_numCoeffs); }
	void						SetColour(int colour)							{ _colour = colour; }
	int							GetColour(void)										{ return(_colour); }
	void						SetDcFlag(int dc)									{ _dcFlag = dc; }
	int							IsDc(void)												{ return(_dcFlag); }

	void						Copy(void* buff);
	void						CopyRow(int row, void* buff);
	void						CopyCol(int col, void* buff);
	void						Zero(void);
  void            Zero(int start, const int* path)  {   for(int i = start; i < _length; i++) _pBlk[path[i]] = 0; }

/// Private methods.
protected:
	void DeleteMem(void);

/// Public data block members.
public:
	/// Location aware members.
	int _offX;				///< Block coord offset from top left of macroblock.
	int _offY;
	/// Neighborhood access for determining context-aware variables.
	BlockH264* _blkAbove;
	BlockH264* _blkLeft;

/// Block constants.
public:
	static const int LUM		= 0;	///< Used for _colour values.
	static const int CB			= 1;
	static const int CR			= 2;

/// Private data block members.
protected:
	/// Code/no code flag. Inverse of the Macroblock level skip flag, but for this block 
	/// only. Is used to help determine the MB type and coded block pattern.
	int							_coded;
	/// The block variables.
	short*					_pBlk;
	int							_width;
	int							_height;
	int							_length;		///< = _width * _height.
	int							_colour;		///< = {LUM, CB, CR}
	int							_dcFlag;		///< Indicates that the block holds DC components only.
	/// Status or temp storage variables.
	int							_numCoeffs;	///< Temp holder for total no. of coeffs after an RleEncode or RleDecode.
	/// The block overlay for block functions.
	OverlayMem2Dv2* _blk;
  
	/// Mem status.
	int	_ready;

};// end class BlockH264.

#endif	//_BLOCKH264_H
========== END FILE: CodecUtils/BlockH264.h ==========

========== BEGIN FILE: CodecUtils/CAVLCH264Impl.cpp ==========
Bundle entry: 10
Original bytes: 26706
Original SHA-256: 1eacab6776d387befacf149b0eb408ef571ac3870c524c85f1e5cbbe31459632
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CAVLCH264Impl

TAG						: CLRLH264I

FILE NAME			: CAVLCH264Impl.cpp

DESCRIPTION		: A class to implement a CAVLC codec on the 2-D quantised 
								integer transformed and quantised coeffs of a coded block 
								as defined in the H.264 standard. It implements the 
								IRunLengthCodec interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "IBitStreamReader.h"
#include "IBitStreamWriter.h"
#include "CAVLCH264Impl.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int CAVLCH264Impl::zigZag8x8Pos[64] =
{
	 0,	 1,	 8, 16,	 9,	 2,	 3,	10,
	17,	24,	32,	25,	18,	11,	 4,	 5,
	12,	19,	26,	33,	40,	48,	41,	34,
	27,	20,	13,	 6,	 7,	14,	21,	28,
	35,	42,	49,	56,	57,	50,	43,	36,
	29,	22,	15,	23,	30,	37,	44,	51,
	58,	59,	52,	45,	38,	31,	39,	46,
	53,	60,	61,	54,	47,	55,	62,	63
};

const int CAVLCH264Impl::zigZag4x4Pos[16] =
{
	 0,	 1,	 4,  8,
	 5,	 2,	 3,	 6,
	 9,	12,	13,	10,
	 7,	11,	14,	15
};

const int CAVLCH264Impl::zigZag2x2Pos[4] =
{
	 0,	 1,
	 2,	 3
};

/*
---------------------------------------------------------------------------
	Construction and Destruction.
---------------------------------------------------------------------------
*/
CAVLCH264Impl::CAVLCH264Impl(void)
{
	/// Default to 4x4.
	_mode					= Mode4x4;
	_zigZag				= zigZag4x4Pos;
	_maxNumCoeff	= 16;
	_numCoeff			= 0;

	_numTotNeighborCoeff	= 0;
	_dcSkip								= 0;

	/// Vlc encoders/decoders
	_pCoeffTokenVlcEncoder	= NULL;
	_pCoeffTokenVlcDecoder	= NULL;
	_pPrefixVlcEncoder			= NULL;;
	_pPrefixVlcDecoder			= NULL;;
	_pTotalZerosVlcEncoder	= NULL;;
	_pTotalZerosVlcDecoder	= NULL;;
	_pRunBeforeVlcEncoder		= NULL;;
	_pRunBeforeVlcDecoder		= NULL;;

}//end constructor.

CAVLCH264Impl::~CAVLCH264Impl(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode the input to a CAVLC bit stream.
Encode the input 2-D block of IT coeffs into the output run-level bit stream. 
A NULL stream will switch the encoder to count the number of bits used without 
writing to stream. Error codes are:
	-1 = Vlc error (no such symbol).
	-2 = Stream is full.
@param in		:	Input block to encode.
@param rle	:	Run-level encoded stream.
@return			: Total num of encoded bits. Negative values for errors.
*/
int CAVLCH264Impl::Encode(void* in, void* stream)
{
	/// Interpret the param list for this implementation.
	short*						coeffLevel	= (short *)in;
	IBitStreamWriter*	pBsw				= (IBitStreamWriter *)stream;

	int totalEncBits = 0;
	int level[64]; ///< Max size is for 8x8.
	int runBefore[64];
	int totalCoeff		= 0;
	int trailingOnes	= 0;
	int trailingOnesSignFlag[3];
	int totalZeros		= 0;
	int i;

	/// Scan the input in reverse zigzag order and determine the context-aware
	/// variables to code.
	int pos		= 0;	///< A forward array index.
	int count = 0;	///< Local zero counter.
	for(i = (_maxNumCoeff-1); i >= _dcSkip; i--)
	{
		int x = coeffLevel[_zigZag[i]];
		/// Last trailing zeros are ignored and not coded. Wait for the 1st
		/// non-zero coeff.
		if(totalCoeff > 0)
		{
			if(x == 0)
			{
				count++;
				totalZeros++;	///< Count all zeros including any at the head (low freq) end.
			}//end if x == 0...
			else	///< ...a non-zero coeff is detected.
			{
				/// Set the zero run for previous non-zero coeff and advance to next non-zero
				/// pos. Reset the local zero counter.
				runBefore[pos++] = count;
				count = 0;
				/// Load the next non-zero coeff.
				level[pos] = x;
				totalCoeff++;
				/// Only 3 trailing ones are permitted. There must be no non-one values in-between
				/// the trailing ones count.
				if((trailingOnes < 3)&&(trailingOnes == (totalCoeff-1)))
				{
					if((x == -1)||(x == 1))	///< Trailing one.
					{
						if(x == -1)
							trailingOnesSignFlag[trailingOnes] = 1;
						else	///< x == 1.
							trailingOnesSignFlag[trailingOnes] = 0;
						trailingOnes++;
					}//end if x...
				}//end if trailingOnes...
			}//end else...
		}//end if totalCoeff...
		else	
		{
			if(x != 0)	///< 1st non-zero coeff.
			{
				level[pos] = x;
				totalCoeff++;
				if((x == -1)||(x == 1))	///< Trailing one?
				{
					if(x == -1)
						trailingOnesSignFlag[0] = 1;
					else	///< x == 1.
						trailingOnesSignFlag[0] = 0;
					trailingOnes++;
				}//end if x...
			}//end if x != 0...
		}//end else...
	}//end for i...

	/// Get the Vlc codes for each context-aware variable are write them to
	/// the bit stream keeping count of the total no. of bits consumed.
	int lclNumBits;

	/// Write the coeff_token to the bit stream with error detection.
	lclNumBits = _pCoeffTokenVlcEncoder->Encode3(totalCoeff, trailingOnes, _numTotNeighborCoeff);
	if(pBsw != NULL)
	{
		if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
			pBsw->Write(lclNumBits, _pCoeffTokenVlcEncoder->GetCode());
		else	///< Stream full error.
			return(STREAM_ACCESS_DENIED);
	}//end if pBsw...
	if(lclNumBits > 0)
		totalEncBits += lclNumBits;
	else	///< Vlc symbol not recognised error.
		return(VLC_SYMBOL_NOT_RECOGNISED);

	/// Proceed if there is anything to code.
	if(totalCoeff > 0)
	{
		int suffixLength	= 0;	///< Default and most likely case.
		if((totalCoeff > 10) && (trailingOnes < 3))	///< Special condition for spatially active blocks.
			suffixLength = 1;

		/// Write all the non-zero coeffs that are stored in reverse order from high freq 
		/// to low freq starting with the trailing ones.
		for(i = 0; i < totalCoeff; i++)
		{
			if(i < trailingOnes)
			{
				/// trailing_ones_sign_flag is written to the bit stream.
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= 1)
						pBsw->Write(trailingOnesSignFlag[i]);
					else	///< Stream full error.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				totalEncBits++;
			}//end if i...
			else
			{
				/// Translate the level +/- codes into even/odd levelCode.
				int levelCode;
				if(level[i] > 0)	///< + is even.
					levelCode = (2*level[i]) - 2;
				else							///< - is odd.
					levelCode = -((2*level[i]) + 1);

				if((i == trailingOnes) && (trailingOnes < 3))	///< Special condition for non-ones in the trailing 3 positions.
					levelCode -= 2;

				/// Determine the prefix, suffix length & level code before writing to the stream.
				int done						= 0;
				int levelPrefix			= 0;
				int levelSuffix			= 0;
				int levelSuffixSize = suffixLength;
				/// Use levelPrefix = 14 as an ESC code for 1st trailing large 
				/// levels from 14 - 29 range.
				if(suffixLength == 0)
				{
					if((levelCode >= 14)&&(levelCode <= 29))
					{
						levelSuffixSize = 4;
						levelSuffix			= (levelCode - 14) & 0x0000000F;
						levelPrefix			= 14;
						done						= 1;	///< Early exit.
					}//end if encLevelCode...
				}//end if !suffixLength...

				if(!done)
				{
					/// Max possible levelCode with this suffixLength and 
					/// levelPrefix less than 15.
					int maxLevelCode = (14 << suffixLength) + ~(0xFFFFFFFF << suffixLength);

					/// Extract level prefix and suffix from the levelCode.
					if(levelCode <= maxLevelCode)
					{
						levelPrefix = levelCode >> suffixLength;
						levelSuffix = levelCode & ~(0xFFFFFFFF << suffixLength);
					}//end if encLevelCode...
					else	///< Large code levels.
					{
						/// Entering here the levelCode is always greater than the level 
						/// associated with a max prefix = 15 therefore it can be subtracted 
						/// to promote smaller levels.
						levelCode -= (15 << suffixLength);
						/// For a suffixLength of zero the max levelCode can be further 
						/// reduced by 15 as levelCodes less than 30 are catered for by
						/// the ESC code with LevelPrefix = 14 described above.
						if(suffixLength == 0)
							levelCode -= 15;
						/// The levelPrefix to set defines the range between octaves in
						/// the following way:
						///	LevelPrefix		Range (2^(levelPrefix-3)) offset by (2^x - 1)(2^12)
						///	15						0..((2^12)-1)
						///	16												2^12..((2^13)+(2^12)-1)
						///	17																							((2^13)+(2^12))..((2^14)+(2^12)-1)
						///	etc.
						/// Note that the min value for each range can be subtracted to save
						/// 1 bit per range.
						levelPrefix = 15;
						/// Iterate the levelPrefix by checking if levelCode is larger than the min
						/// levelCode for the next larger range. Put a hard limit max bit size to 32 (= 35 - 3).
						while((levelCode >= ((1 << (levelPrefix-2)) - 4096))&&(levelPrefix < 35))
							levelPrefix++;
						if(levelPrefix >= 16)
							levelCode -= (1 << (levelPrefix-3)) - 4096;	///< Reduce by min value for this range.

						levelSuffixSize = levelPrefix - 3;
						levelSuffix			= levelCode & ~(0xFFFFFFFF << levelSuffixSize);
					}//end else...
				}//end if !done...

				/// Write the level_prefix and V to the bit stream.
				lclNumBits = _pPrefixVlcEncoder->Encode(levelPrefix);
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= (lclNumBits + levelSuffixSize))
					{
						pBsw->Write(lclNumBits, _pPrefixVlcEncoder->GetCode());
						pBsw->Write(levelSuffixSize, levelSuffix);
					}//end if GetStreamBitsRemaining...
					else	///< Stream is full.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				if(lclNumBits > 0)
					totalEncBits += (lclNumBits + levelSuffixSize);
				else
					return(VLC_SYMBOL_NOT_RECOGNISED);

				/// If the level is above a threshold then increment suffixLength for next write. Note
				/// suffixLength cannot be longer than 6 bits.
				if(suffixLength == 0)
					suffixLength = 1;
				int absLevel = level[i];
				if(absLevel < 0)
					absLevel = -absLevel;
				if((absLevel > (3 << (suffixLength-1))) && (suffixLength < 6))
					suffixLength++;
			}//end else...
		}//end for i...

		/// Encode and write the total number of zeros in-between the non-zero 
		/// coeffs to the bit stream.
		int zerosLeft = totalZeros;
		if(totalCoeff < (_maxNumCoeff - _dcSkip))	///< i.e. there are some zeros.
		{
			/// The total_zeros code is dependent on totalCoeff.
			lclNumBits = _pTotalZerosVlcEncoder->Encode2(totalZeros, totalCoeff);
			if(pBsw != NULL)
			{
				if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
					pBsw->Write(lclNumBits, _pTotalZerosVlcEncoder->GetCode());
				else	///< Stream is full.
					return(STREAM_ACCESS_DENIED);
			}//end if pBsw...
			if(lclNumBits > 0)
				totalEncBits += lclNumBits;
			else
				return(VLC_SYMBOL_NOT_RECOGNISED);

			/// The variable pos = total length of runBefore[] array, one less than
			/// the level[] array.
			for(i = 0; (i < pos) && zerosLeft; i++)
			{
				lclNumBits = _pRunBeforeVlcEncoder->Encode2(runBefore[i], zerosLeft);
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
						pBsw->Write(lclNumBits, _pRunBeforeVlcEncoder->GetCode());
					else	///< Stream is full.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				if(lclNumBits > 0)
					totalEncBits += lclNumBits;
				else
					return(VLC_SYMBOL_NOT_RECOGNISED);
				/// Update the context.
				zerosLeft -= runBefore[i];
			}//end for i...
		}//end if totalCoeff...

	}//end if totalCoeff...

	/// Store total coeffs for this encode session.
	_numCoeff = totalCoeff;

	return(totalEncBits);
}//end Encode.

/** Decode a CAVLC bit stream to the output.
Decode the input run-level bit stream into the output 2-D block of IT coeffs. It
is unknown how many bits will come off the stream for the next read so the error
checking only looks for end of the stream. A read is non-destructive so reading
past the end of the stream will not do bad things. Error codes are:
	-1 = Vlc error (non-existent symbol).
	-2 = Stream is empty.
@param stream	:	Run-level stream to decode.
@param out		:	Output block generated by the decode.
@return				: Total num of decoded bits. Negative values for errors.
*/
int CAVLCH264Impl::Decode(void* stream, void* out)
{
	/// Interpret the param list for this implementation.
	IBitStreamReader* pBsr				= (IBitStreamReader *)stream;
	short*						coeffLevel	= (short *)out;

	int totalDecBits = 0;
	int lclNumBits;
	int level[64]; ///< Max size is for 8x8.
	int runBefore[64];
	int i;

	/// Clear output array.
	memset(coeffLevel, 0, sizeof(short) * _maxNumCoeff);

	/// coeff_token is parsed from the bit stream and decoded to give the totalCoeff
	/// and trailingOnes where the vlc table selection is indicated by the 3rd symbol.
	int totalCoeff,trailingOnes;
	if(pBsr->GetStreamBitsRemaining() > 0)
		lclNumBits = _pCoeffTokenVlcDecoder->Decode3(pBsr, &totalCoeff, &trailingOnes, &_numTotNeighborCoeff);
	else	///< Stream is empty.
		return(STREAM_ACCESS_DENIED);
	if(lclNumBits > 0)
		totalDecBits += lclNumBits;
	else	///< Vlc error.
		return(VLC_SYMBOL_NOT_RECOGNISED);

	/// Only requires decoding if there are any non-zero coeffs.
	if(totalCoeff > 0)
	{
		int suffixLength	= 0;	///< Default and most likely case.
		if((totalCoeff > 10) && (trailingOnes < 3))	///< Special condition for spatially active blocks.
			suffixLength = 1;

		/// Extract all the non-zero coeffs that are stored in reverse order from high freq 
		/// to low freq starting with the trailing ones.
		for(i = 0; i < totalCoeff; i++)
		{
			if(i < trailingOnes)
			{
				int trailingOnesSignFlag;
				/// trailing_ones_sign_flag is parsed from the bit stream.
				if(pBsr->GetStreamBitsRemaining() > 0)
					trailingOnesSignFlag = pBsr->Read();
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				totalDecBits++;
				level[i] = 1 - 2*trailingOnesSignFlag;
			}//end if i...
			else
			{
				int levelPrefix;
				/// level_prefix is parsed from the bit stream by counting zeros.
				if(pBsr->GetStreamBitsRemaining() > 0)
					levelPrefix = _pPrefixVlcDecoder->Decode(pBsr);
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				lclNumBits = _pPrefixVlcDecoder->GetNumDecodedBits();
				if(lclNumBits > 0)
					totalDecBits += lclNumBits;
				else	///< Vlc error.
					return(VLC_SYMBOL_NOT_RECOGNISED);

				int levelSuffixSize = suffixLength;
				/// Modify the suffix bits to extract large values.
				if(levelPrefix >= 15)
					levelSuffixSize = levelPrefix - 3;
				else if((levelPrefix == 14)&&(suffixLength == 0))
					levelSuffixSize = 4;

				int levelSuffix = 0;
				if(levelSuffixSize > 0)
				{
					/// level_suffix is parsed from the bit stream.
					if(pBsr->GetStreamBitsRemaining() >= levelSuffixSize)
						levelSuffix = pBsr->Read(levelSuffixSize);
					else	///< Stream is empty.
						return(STREAM_ACCESS_DENIED);
					totalDecBits += levelSuffixSize;
				}//end if levelSuffixSize...

				/// Shift levelPrefix left into bit position defined by suffixLength
				/// and add the levelSuffix.
				int levelCode;
				if(levelPrefix < 15)
					levelCode = (levelPrefix << suffixLength) + levelSuffix;
				else
					levelCode = (15 << suffixLength) + levelSuffix;

				if((levelPrefix >= 15) && (suffixLength == 0))	///< Special condition for large high freq trailing levels.
					levelCode += 15;

				if(levelPrefix >= 16)
					levelCode += (1 << (levelPrefix-3)) - 4096;	///< Special condition for all large values.

				if((i == trailingOnes) && (trailingOnes < 3))	///< Special condition for non-ones in the trailing 3 positions.
					levelCode += 2;

				/// Translate the levelCode into the +/- level stored as even/odd codes.
				if(levelCode & 1)	///< Odd is -.
					level[i] = (-levelCode - 1) >> 1;
				else							///< Even is +.
					level[i] = (levelCode + 2) >> 1;

				/// If the level is above a threshold then increment suffixLength for next parse. Note
				/// suffixLength cannot be longer than 6 bits.
				if(suffixLength == 0)
					suffixLength = 1;
				int absLevel = level[i];
				if(absLevel < 0)
					absLevel = -absLevel;
				if((absLevel > (3 << (suffixLength-1))) && (suffixLength < 6))
					suffixLength++;
			}//end else...
		}//end for i...

		/// Get the total no. of zeros inbetween the non-zero coeffs.
		int zerosLeft = 0;
		if(totalCoeff < (_maxNumCoeff - _dcSkip))	///< i.e. there are some zeros.
		{
			/// total_zeros is parsed from the bit stream and is dependent on totalCoeff.
			if(pBsr->GetStreamBitsRemaining() > 0)
				lclNumBits = _pTotalZerosVlcDecoder->Decode2(pBsr, &zerosLeft, &totalCoeff);
			else	///< Stream is empty.
				return(STREAM_ACCESS_DENIED);
			if(lclNumBits > 0)
				totalDecBits += lclNumBits;
			else	///< Vlc error.
				return(VLC_SYMBOL_NOT_RECOGNISED);
		}//end if totalCoeff...

		/// Set the run_before values for each non-zero coeff. Note that the last
		/// (low freq) non-zero coeff run_before does not need decoding because it 
		/// is implicit.
		for(i = 0; i < (totalCoeff-1); i++)
		{
			runBefore[i] = 0;
			if(zerosLeft > 0)
			{
				/// run_before is parsed from the bit stream and is dependent on the current zerosLeft.
				if(pBsr->GetStreamBitsRemaining() > 0)
					lclNumBits = _pRunBeforeVlcDecoder->Decode2(pBsr, &(runBefore[i]), &zerosLeft);
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				if(lclNumBits > 0)
					totalDecBits += lclNumBits;
				else	///< Vlc error.
					return(VLC_SYMBOL_NOT_RECOGNISED);
			}//end if zerosLeft...
			zerosLeft -= runBefore[i];
		}//end for i...
		runBefore[totalCoeff-1] = zerosLeft;	///< Set the implicit run_before.

		/// Load the level non-zero coeffs into the output array in reverse order and
		/// with zigzag conversion. The coeff level array was initialised to zeros so
		/// only non-zero coeffs need to be added.
		int coeffNum = -1;
		for(i = (totalCoeff-1); i >= 0; i--)
		{
			coeffNum += (runBefore[i] + 1);
			coeffLevel[_zigZag[coeffNum + _dcSkip]] = (short)(level[i]);
		}//end for i...

	}//end if totalCoeff...

	/// Store total coeffs for this decode session.
	_numCoeff = totalCoeff;

	return(totalDecBits);
}//end Decode.

/** Set the codec mode.
The mode defines the block size choice in this implementation.
@param mode	:	Block size selection defined by class consts.
@return			: none.
*/
void CAVLCH264Impl::SetMode(int mode)
{
	_mode = mode;
	switch(mode)
	{
		case Mode2x2:
			_zigZag				= zigZag2x2Pos;
			_maxNumCoeff	= 4;
			break;
		case Mode4x4:
			_zigZag				= zigZag4x4Pos;
			_maxNumCoeff	= 16;
			break;
		case Mode8x8:
			_zigZag				= zigZag8x8Pos;
			_maxNumCoeff	= 64;
			break;
		default:
			_mode					= Mode4x4;
			_zigZag				= zigZag4x4Pos;
			_maxNumCoeff	= 16;
			break;
	}//end switch mode...
}//end SetMode.

/** Set the codec parameters.
The IDs are defined by the class consts and values by the 
members. Do nothing if the param is not defined in this 
implementation.
@param paramID	: Parameter to set.
@param paramVal	: Parameter value.
@return					: none.
*/
void CAVLCH264Impl::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case NUM_TOT_NEIGHBOR_COEFF_ID:
			_numTotNeighborCoeff = paramVal;
			break;
		case DC_SKIP_FLAG_ID:
			_dcSkip = paramVal;
			break;
	}//end switch paramID...
}//end SetParameter.

/** Get the codec parameters.
Return -1 if the param is not defined in this implementation.
@param paramID	: Parameter to get.
@return					: Param value.
*/
int CAVLCH264Impl::GetParameter(int paramID)
{
	int res = -1;
	switch(paramID)
	{
		case NUM_TOT_NEIGHBOR_COEFF_ID:
			res = _numTotNeighborCoeff;
			break;
		case DC_SKIP_FLAG_ID:
			res = _dcSkip;
			break;
		case NUM_TOT_COEFF_ID:
			res = _numCoeff;
			break;
	}//end switch paramID...

	return(res);
}//end GetParameter.

/*
---------------------------------------------------------------------------
	Unit Test Methods.
---------------------------------------------------------------------------
*/
/** Test level prefix & suffix combinations.
Iterate through a large range of level codes for all possible combinations
of suffix lengths. This method tests the algorithm not in-place.
@return	: 1 = success, 0 = failure.
*/
int CAVLCH264Impl::TestLevelPrefixSuffix(void)
{
	int result = 1;

	/// Variables to emulate.
	int levelPrefix, levelSuffix, levelSuffixSize;
	int encLevelCode, decLevelCode, suffixLength;
	int upper, lower;

	for(suffixLength = 0; suffixLength <= 6; suffixLength++)
		for(encLevelCode = 1; encLevelCode < 65536; encLevelCode++)
		{
			/// --- Encode suffix length & level code pairs ---

			int done = 0;
			levelSuffixSize = suffixLength;
			/// Use levelPrefix = 14 as an ESC code for 1st trailing large 
			/// levels from 14 - 29 range.
			if(suffixLength == 0)
			{
				if((encLevelCode >= 14)&&(encLevelCode <= 29))
				{
					levelSuffixSize = 4;
					levelSuffix			= (encLevelCode - 14) & 0x0000000F;
					levelPrefix			= 14;
					done						= 1;
				}//end if encLevelCode...
			}//end if !suffixLength...

			if(!done)
			{
				/// Max possible levelCode with this suffixLength and 
				/// levelPrefix less than 15.
				int maxLevelCode = (14 << suffixLength) + ~(0xFFFFFFFF << suffixLength);

				/// Extract level prefix and suffix.
				if(encLevelCode <= maxLevelCode)
				{
					levelPrefix = encLevelCode >> suffixLength;
					levelSuffix = encLevelCode & ~(0xFFFFFFFF << suffixLength);
				}//end if encLevelCode...
				else	///< Large code levels.
				{
					int lev = encLevelCode;
					/// Entering here the levelCode is always greater than the level 
					/// associated with a max prefix = 15 therefore it can be subtracted 
					/// to promote smaller levels.
					lev -= (15 << suffixLength);
					/// For a suffixLength of zero the max levelCode can be further 
					/// reduced by 15 as levelCodes less than 30 are catered for by
					/// the ESC code with LevelPrefix = 14 described above.
					if(suffixLength == 0)
						lev -= 15;
					/// The levelPrefix to set defines the range between octaves in
					/// the following way:
					///	LevelPrefix		Range (2^(levelPrefix-3)) offset by (2^x - 1)(2^12)
					///	15						0..((2^12)-1)
					///	16												2^12..((2^13)+(2^12)-1)
					///	17																							((2^13)+(2^12))..((2^14)+(2^12)-1)
					///	etc.
					/// Note that the min value for each range can be subtracted to save
					/// 1 bit per range.
					levelPrefix = 15;
					/// Iterate the levelPrefix by checking if levelCode is larger than the min
					/// levelCode for the next larger range. Put a hard limit max bit size to 32 (= 35 - 3).
					while((lev >= ((1 << (levelPrefix-2)) - 4096))&&(levelPrefix < 35))
						levelPrefix++;
					if(levelPrefix >= 16)
						lev -= (1 << (levelPrefix-3)) - 4096;	///< Reduce by min value for this range.

					levelSuffixSize = levelPrefix - 3;
					levelSuffix			= lev & ~(0xFFFFFFFF << levelSuffixSize);
				}//end else...
			}//end if !done...

			/// Emulate writing to stream.
			upper = levelPrefix;
			lower = levelSuffix;

			/// --- Decode suffix length & level code pairs ---

			/// Emulate reading levelPrefix from stream.
			levelPrefix = upper;

			levelSuffixSize = suffixLength;
			/// Modify the suffix bits to extract large values.
			if(levelPrefix >= 15)
				levelSuffixSize = levelPrefix - 3;
			else if((levelPrefix == 14)&&(suffixLength == 0))
				levelSuffixSize = 4;

			levelSuffix = 0;
			if(levelSuffixSize > 0)
			{
				/// Emulate level_suffix is parsed from the bit stream.
				levelSuffix = lower & ~(0xFFFFFFFF << levelSuffixSize);
			}//end if levelSuffixSize...

			/// Shift levelPrefix left into bit position defined by suffixLength
			/// and add the levelSuffix.
			if(levelPrefix < 15)
				decLevelCode = (levelPrefix << suffixLength) + levelSuffix;
			else
				decLevelCode = (15 << suffixLength) + levelSuffix;

			if((levelPrefix >= 15) && (suffixLength == 0))	///< Special condition for large high freq trailing levels.
				decLevelCode += 15;

			if(levelPrefix >= 16)
				decLevelCode += (1 << (levelPrefix-3)) - 4096;	///< Special condition for all large values.

			if(decLevelCode != encLevelCode)
				result = 0;
		}//end for suffixLength & encLevelCode...

		return(result);
}//end TestLevelPrefixSuffix.

========== END FILE: CodecUtils/CAVLCH264Impl.cpp ==========

========== BEGIN FILE: CodecUtils/CAVLCH264Impl.h ==========
Bundle entry: 11
Original bytes: 5775
Original SHA-256: 1f6c4d9ce7c35bca1f71401f69978d3255d0c5dc5ee8d6632d31432c1b1db2b4
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CAVLCH264Impl

TAG						: CAVLCH264I

FILE NAME			: CAVLCH264Impl.h

DESCRIPTION		: A class to implement a CAVLC codec on the 2-D quantised 
								integer transformed and quantised coeffs of a coded block 
								as defined in the H.264 standard. It implements the 
								IContextAwareRunLevelCodec interface.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _CAVLCH264IMPL_H
#define _CAVLCH264IMPL_H

#pragma once

#include "IContextAwareRunLevelCodec.h"
#include "IVlcEncoder.h"
#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CAVLCH264Impl : public IContextAwareRunLevelCodec
{
public:
	CAVLCH264Impl(void);
	virtual ~CAVLCH264Impl(void);

/// Interface implementation.
public:
	/** Encode the input to a CAVLC bit stream.
	Encode the input 2-D block of IT coeffs into the output 
	run-level bit stream.
	@param in		:	Input block to encode.
	@param rle	:	Run-level encoded stream.
	@return			: Total num of encoded bits. Negative values for errors.
	*/
	int Encode(void* in, void* stream);

	/** Decode a CAVLC bit stream to the output.
	Decode the input run-level bit stream into the
	output 2-D block of IT coeffs.
	@param stream	:	Run-level stream to decode.
	@param out		:	Output block generated by the decode.
	@return				: Total num of decoded bits. Negative values for errors.
	*/
	int Decode(void* stream, void* out);

	void	SetMode(int mode);
	int		GetMode(void)			{ return(_mode); }

	void	SetParameter(int paramID, int paramVal);
	int		GetParameter(int paramID);

/// Implementation specific methods.
public:
	/// Vlc encoders and decoders are used by (associated with) this class and
	/// are required to be set up before encoding/decoding takes place.

	/** Set vlc encoder/decoder to use.
	@param	vlc	: Vlc encoder reference.
	@return			: None.
	*/
	void SetTokenCoeffVlcEncoder(IVlcEncoder* vlc)	{ _pCoeffTokenVlcEncoder = vlc; }
	void SetTokenCoeffVlcDecoder(IVlcDecoder* vlc)	{ _pCoeffTokenVlcDecoder = vlc; }
	void SetPrefixVlcEncoder(IVlcEncoder* vlc)			{ _pPrefixVlcEncoder = vlc; }
	void SetPrefixVlcDecoder(IVlcDecoder* vlc)			{ _pPrefixVlcDecoder = vlc; }
	void SetTotalZerosVlcEncoder(IVlcEncoder* vlc)	{ _pTotalZerosVlcEncoder = vlc; }
	void SetTotalZerosVlcDecoder(IVlcDecoder* vlc)	{ _pTotalZerosVlcDecoder = vlc; }
	void SetRunBeforeVlcEncoder(IVlcEncoder* vlc)		{ _pRunBeforeVlcEncoder = vlc; }
	void SetRunBeforeVlcDecoder(IVlcDecoder* vlc)		{ _pRunBeforeVlcDecoder = vlc; }

/// Class constants.
public:
	static const int zigZag8x8Pos[64];
	static const int zigZag4x4Pos[16];
	static const int zigZag2x2Pos[4];

public:
	static const int VLC_SYMBOL_NOT_RECOGNISED	= -1;
	static const int STREAM_ACCESS_DENIED				= -2; ///< Full for write & Empty for read.

	/// Class members.
protected:
	const int*	_zigZag;			///< Active selection of const arrays.
	int					_mode;				///< Active mode.
	int					_maxNumCoeff;	///< Num of coeffs in block e.g. 4x4 = 16.
	int					_numCoeff;		///< After encoding or decoding store the no. of coeff for this block.

	/// Parameters for this class for each param ID.
	int					_numTotNeighborCoeff;	///< VLC table selection is based on total coeffs of neighbors.
	int					_dcSkip;							///< All run length coding must ignore the DC coeff in position zero.

	/// Associated Vlc encoders/decoders.
	IVlcEncoder*	_pCoeffTokenVlcEncoder;
	IVlcDecoder*	_pCoeffTokenVlcDecoder;
	IVlcEncoder*	_pPrefixVlcEncoder;
	IVlcDecoder*	_pPrefixVlcDecoder;
	IVlcEncoder*	_pTotalZerosVlcEncoder;
	IVlcDecoder*	_pTotalZerosVlcDecoder;
	IVlcEncoder*	_pRunBeforeVlcEncoder;
	IVlcDecoder*	_pRunBeforeVlcDecoder;

	/// Test code.
public:
	static int TestLevelPrefixSuffix(void);

};// end class CAVLCH264Impl.

#endif	//_CAVLCH264IMPL_H
========== END FILE: CodecUtils/CAVLCH264Impl.h ==========

========== BEGIN FILE: CodecUtils/CAVLCH264Impl2.cpp ==========
Bundle entry: 12
Original bytes: 23422
Original SHA-256: 166e46574c293d8a11f74bdf898ff9abc571cfe51dc32a65b0f19b5e552e335a
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CAVLCH264Impl2

TAG						: CLRLH264I2

FILE NAME			: CAVLCH264Impl2.cpp

DESCRIPTION		: A class to implement a CAVLC codec on the 2-D quantised 
								integer transformed and quantised coeffs of a coded block 
								as defined in the H.264 standard. It implements the 
								IRunLengthCodec interface. This 2nd implementation operates
                on OverlayMem2Dv2 classes and not on the data directly. 

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "IBitStreamReader.h"
#include "IBitStreamWriter.h"
#include "CAVLCH264Impl2.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int CAVLCH264Impl2::zigZag8x8PosX[64] =
{
	 0,	 1,	 0,  0,	 1,	 2,	 3,	 2,
	 1,  0,	 0,	 1,	 2,	 3,	 4,	 5,
	 4,	 3,	 2,	 1,	 0,	 0,	 1,	 2,
	 3,	 4,	 5,	 6,	 7,	 6,	 5,	 4,
	 3,	 2,	 1,	 0,	 1,	 2,	 3,	 4,
	 5,	 6,	 7,	 7,	 6,	 5,	 4,	 3,
	 2,	 3,	 4,	 5,	 6,	 7,	 7,	 6,
	 5,	 4,	 5,	 6,	 7,	 7,	 6,	 7
};

const int CAVLCH264Impl2::zigZag8x8PosY[64] =
{
	 0,	 0,	 1,  2,	 1,	 0,	 0,	 1,
	 2,	 3,	 4,	 3,	 2,	 1,	 0,	 0,
	 1,	 2,	 3,	 4,	 5,	 6,	 5,	 4,
	 3,	 2,	 1,	 0,	 0,	 1,	 2,	 3,
	 4,	 5,	 6,	 7,	 7,	 6,	 5,	 4,
	 3,	 2,	 1,	 2,	 3,	 4,	 5,	 6,
	 7,	 7,	 6,	 5,	 4,	 3,	 4,	 5,
	 6,	 7,	 7,	 6,	 5,	 6,	 7,	 7
};

const int CAVLCH264Impl2::zigZag4x4PosX[16] =
{
	 0,	 1,	 0,  0,
	 1,	 2,	 3,	 2,
	 1,	 0,	 1,	 2,
	 3,	 3,	 2,	 3
};

const int CAVLCH264Impl2::zigZag4x4PosY[16] =
{
	 0,	 1,	 1,  2,
	 1,	 0,	 0,	 1,
	 2,	 3,	 3,	 2,
	 1,	 2,	 3,	 3
};

const int CAVLCH264Impl2::zigZag2x2PosX[4] =
{
	 0,	 1,
	 0,	 1
};

const int CAVLCH264Impl2::zigZag2x2PosY[4] =
{
	 0,	 0,
	 1,	 1
};

/*
---------------------------------------------------------------------------
	Construction and Destruction.
---------------------------------------------------------------------------
*/
CAVLCH264Impl2::CAVLCH264Impl2(void)
{
	/// Default to 4x4.
	_mode					= Mode4x4;
	_zigZagX			= zigZag4x4PosX;
	_zigZagX			= zigZag4x4PosY;
	_maxNumCoeff	= 16;
	_numCoeff			= 0;

	_numTotNeighborCoeff	= 0;
	_dcSkip								= 0;

	/// Vlc encoders/decoders
	_pCoeffTokenVlcEncoder	= NULL;
	_pCoeffTokenVlcDecoder	= NULL;
	_pPrefixVlcEncoder			= NULL;;
	_pPrefixVlcDecoder			= NULL;;
	_pTotalZerosVlcEncoder	= NULL;;
	_pTotalZerosVlcDecoder	= NULL;;
	_pRunBeforeVlcEncoder		= NULL;;
	_pRunBeforeVlcDecoder		= NULL;;

}//end constructor.

CAVLCH264Impl2::~CAVLCH264Impl2(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode the input to a CAVLC bit stream.
Encode the input 2-D block of IT coeffs into the output run-level bit stream. The
overlay dimensions and origin must be defined before calling this method and therefore,
are assumed to be correct for this size block. A NULL stream will switch the encoder 
to count the number of bits used without 
writing to stream. Error codes are:
	-1 = Vlc error (no such symbol).
	-2 = Stream is full.
@param in		:	Input block overlay to encode.
@param rle	:	Run-level encoded stream.
@return			: Total num of encoded bits. Negative values for errors.
*/
int CAVLCH264Impl2::Encode(void* in, void* stream)
{
	/// Interpret the param list for this implementation.
	OverlayMem2Dv2*		coeffLevel	= (OverlayMem2Dv2 *)in;
	IBitStreamWriter*	pBsw				= (IBitStreamWriter *)stream;

	int totalEncBits = 0;
	int level[64]; ///< Max size is for 8x8.
	int runBefore[64];
	int totalCoeff		= 0;
	int trailingOnes	= 0;
	int trailingOnesSignFlag[3];
	int totalZeros		= 0;
	int i;

	/// Scan the input in reverse zigzag order and determine the context-aware
	/// variables to code.
	int pos		= 0;	///< A forward array index.
	int count = 0;	///< Local zero counter.
	for(i = (_maxNumCoeff-1); i >= _dcSkip; i--)
	{
		int x = coeffLevel->Read(_zigZagX[i], _zigZagY[i]);
		/// Last trailing zeros are ignored and not coded. Wait for the 1st
		/// non-zero coeff.
		if(totalCoeff > 0)
		{
			if(x == 0)
			{
				count++;
				totalZeros++;	///< Count all zeros including any at the head (low freq) end.
			}//end if x == 0...
			else	///< ...a non-zero coeff is detected.
			{
				/// Set the zero run for previous non-zero coeff and advance to next non-zero
				/// pos. Reset the local zero counter.
				runBefore[pos++] = count;
				count = 0;
				/// Load the next non-zero coeff.
				level[pos] = x;
				totalCoeff++;
				/// Only 3 trailing ones are permitted. There must be no non-one values in-between
				/// the trailing ones count.
				if((trailingOnes < 3)&&(trailingOnes == (totalCoeff-1)))
				{
					if((x == -1)||(x == 1))	///< Trailing one.
					{
						if(x == -1)
							trailingOnesSignFlag[trailingOnes] = 1;
						else	///< x == 1.
							trailingOnesSignFlag[trailingOnes] = 0;
						trailingOnes++;
					}//end if x...
				}//end if trailingOnes...
			}//end else...
		}//end if totalCoeff...
		else	
		{
			if(x != 0)	///< 1st non-zero coeff.
			{
				level[pos] = x;
				totalCoeff++;
				if((x == -1)||(x == 1))	///< Trailing one?
				{
					if(x == -1)
						trailingOnesSignFlag[0] = 1;
					else	///< x == 1.
						trailingOnesSignFlag[0] = 0;
					trailingOnes++;
				}//end if x...
			}//end if x != 0...
		}//end else...
	}//end for i...

	/// Get the Vlc codes for each context-aware variable are write them to
	/// the bit stream keeping count of the total no. of bits consumed.
	int lclNumBits;

	/// Write the coeff_token to the bit stream with error detection.
	lclNumBits = _pCoeffTokenVlcEncoder->Encode3(totalCoeff, trailingOnes, _numTotNeighborCoeff);
	if(pBsw != NULL)
	{
		if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
			pBsw->Write(lclNumBits, _pCoeffTokenVlcEncoder->GetCode());
		else	///< Stream full error.
			return(STREAM_ACCESS_DENIED);
	}//end if pBsw...
	if(lclNumBits > 0)
		totalEncBits += lclNumBits;
	else	///< Vlc symbol not recognised error.
		return(VLC_SYMBOL_NOT_RECOGNISED);

	/// Proceed if there is anything to code.
	if(totalCoeff > 0)
	{
		int suffixLength	= 0;	///< Default and most likely case.
		if((totalCoeff > 10) && (trailingOnes < 3))	///< Special condition for spatially active blocks.
			suffixLength = 1;

		/// Write all the non-zero coeffs that are stored in reverse order from high freq 
		/// to low freq starting with the trailing ones.
		for(i = 0; i < totalCoeff; i++)
		{
			if(i < trailingOnes)
			{
				/// trailing_ones_sign_flag is written to the bit stream.
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= 1)
						pBsw->Write(trailingOnesSignFlag[i]);
					else	///< Stream full error.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				totalEncBits++;
			}//end if i...
			else
			{
				/// Translate the level +/- codes into even/odd levelCode.
				int levelCode;
				if(level[i] > 0)	///< + is even.
					levelCode = (2*level[i]) - 2;
				else							///< - is odd.
					levelCode = -((2*level[i]) + 1);

				if((i == trailingOnes) && (trailingOnes < 3))	///< Special condition for non-ones in the trailing 3 positions.
					levelCode -= 2;

				/// Determine the prefix, suffix length & level code before writing to the stream.
				int done						= 0;
				int levelPrefix			= 0;
				int levelSuffix			= 0;
				int levelSuffixSize = suffixLength;
				/// Use levelPrefix = 14 as an ESC code for 1st trailing large 
				/// levels from 14 - 29 range.
				if(suffixLength == 0)
				{
					if((levelCode >= 14)&&(levelCode <= 29))
					{
						levelSuffixSize = 4;
						levelSuffix			= (levelCode - 14) & 0x0000000F;
						levelPrefix			= 14;
						done						= 1;	///< Early exit.
					}//end if encLevelCode...
				}//end if !suffixLength...

				if(!done)
				{
					/// Max possible levelCode with this suffixLength and 
					/// levelPrefix less than 15.
					int maxLevelCode = (14 << suffixLength) + ~(0xFFFFFFFF << suffixLength);

					/// Extract level prefix and suffix from the levelCode.
					if(levelCode <= maxLevelCode)
					{
						levelPrefix = levelCode >> suffixLength;
						levelSuffix = levelCode & ~(0xFFFFFFFF << suffixLength);
					}//end if encLevelCode...
					else	///< Large code levels.
					{
						/// Entering here the levelCode is always greater than the level 
						/// associated with a max prefix = 15 therefore it can be subtracted 
						/// to promote smaller levels.
						levelCode -= (15 << suffixLength);
						/// For a suffixLength of zero the max levelCode can be further 
						/// reduced by 15 as levelCodes less than 30 are catered for by
						/// the ESC code with LevelPrefix = 14 described above.
						if(suffixLength == 0)
							levelCode -= 15;
						/// The levelPrefix to set defines the range between octaves in
						/// the following way:
						///	LevelPrefix		Range (2^(levelPrefix-3)) offset by (2^x - 1)(2^12)
						///	15						0..((2^12)-1)
						///	16												2^12..((2^13)+(2^12)-1)
						///	17																							((2^13)+(2^12))..((2^14)+(2^12)-1)
						///	etc.
						/// Note that the min value for each range can be subtracted to save
						/// 1 bit per range.
						levelPrefix = 15;
						/// Iterate the levelPrefix by checking if levelCode is larger than the min
						/// levelCode for the next larger range. Put a hard limit max bit size to 32 (= 35 - 3).
						while((levelCode >= ((1 << (levelPrefix-2)) - 4096))&&(levelPrefix < 35))
							levelPrefix++;
						if(levelPrefix >= 16)
							levelCode -= (1 << (levelPrefix-3)) - 4096;	///< Reduce by min value for this range.

						levelSuffixSize = levelPrefix - 3;
						levelSuffix			= levelCode & ~(0xFFFFFFFF << levelSuffixSize);
					}//end else...
				}//end if !done...

				/// Write the level_prefix and V to the bit stream.
				lclNumBits = _pPrefixVlcEncoder->Encode(levelPrefix);
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= (lclNumBits + levelSuffixSize))
					{
						pBsw->Write(lclNumBits, _pPrefixVlcEncoder->GetCode());
						pBsw->Write(levelSuffixSize, levelSuffix);
					}//end if GetStreamBitsRemaining...
					else	///< Stream is full.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				if(lclNumBits > 0)
					totalEncBits += (lclNumBits + levelSuffixSize);
				else
					return(VLC_SYMBOL_NOT_RECOGNISED);

				/// If the level is above a threshold then increment suffixLength for next write. Note
				/// suffixLength cannot be longer than 6 bits.
				if(suffixLength == 0)
					suffixLength = 1;
				int absLevel = level[i];
				if(absLevel < 0)
					absLevel = -absLevel;
				if((absLevel > (3 << (suffixLength-1))) && (suffixLength < 6))
					suffixLength++;
			}//end else...
		}//end for i...

		/// Encode and write the total number of zeros in-between the non-zero 
		/// coeffs to the bit stream.
		int zerosLeft = totalZeros;
		if(totalCoeff < (_maxNumCoeff - _dcSkip))	///< i.e. there are some zeros.
		{
			/// The total_zeros code is dependent on totalCoeff.
			lclNumBits = _pTotalZerosVlcEncoder->Encode2(totalZeros, totalCoeff);
			if(pBsw != NULL)
			{
				if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
					pBsw->Write(lclNumBits, _pTotalZerosVlcEncoder->GetCode());
				else	///< Stream is full.
					return(STREAM_ACCESS_DENIED);
			}//end if pBsw...
			if(lclNumBits > 0)
				totalEncBits += lclNumBits;
			else
				return(VLC_SYMBOL_NOT_RECOGNISED);

			/// The variable pos = total length of runBefore[] array, one less than
			/// the level[] array.
			for(i = 0; (i < pos) && zerosLeft; i++)
			{
				lclNumBits = _pRunBeforeVlcEncoder->Encode2(runBefore[i], zerosLeft);
				if(pBsw != NULL)
				{
					if(pBsw->GetStreamBitsRemaining() >= lclNumBits)
						pBsw->Write(lclNumBits, _pRunBeforeVlcEncoder->GetCode());
					else	///< Stream is full.
						return(STREAM_ACCESS_DENIED);
				}//end if pBsw...
				if(lclNumBits > 0)
					totalEncBits += lclNumBits;
				else
					return(VLC_SYMBOL_NOT_RECOGNISED);
				/// Update the context.
				zerosLeft -= runBefore[i];
			}//end for i...
		}//end if totalCoeff...

	}//end if totalCoeff...

	/// Store total coeffs for this encode session.
	_numCoeff = totalCoeff;

	return(totalEncBits);
}//end Encode.

/** Decode a CAVLC bit stream to the output.
Decode the input run-level bit stream into the output 2-D block of IT coeffs. The
overlay dimensions and origin must be defined before calling this method and therefore,
are assumed to be correct for this size block. It is unknown how many bits will come 
off the stream for the next read so the error checking only looks for end of the 
stream. A read is non-destructive so reading past the end of the stream will not 
do bad things. Error codes are:
	-1 = Vlc error (non-existent symbol).
	-2 = Stream is empty.
@param stream	:	Run-level stream to decode.
@param out		:	Output block overlay generated by the decode.
@return				: Total num of decoded bits. Negative values for errors.
*/
int CAVLCH264Impl2::Decode(void* stream, void* out)
{
	/// Interpret the param list for this implementation.
	IBitStreamReader* pBsr				= (IBitStreamReader *)stream;
	OverlayMem2Dv2*		coeffLevel	= (OverlayMem2Dv2 *)out;

	int totalDecBits = 0;
	int lclNumBits;
	int level[64]; ///< Max size is for 8x8.
	int runBefore[64];
	int i;

	/// Clear output array.
  coeffLevel->Clear();
	//memset(coeffLevel, 0, sizeof(short) * _maxNumCoeff);

	/// coeff_token is parsed from the bit stream and decoded to give the totalCoeff
	/// and trailingOnes where the vlc table selection is indicated by the 3rd symbol.
	int totalCoeff,trailingOnes;
	if(pBsr->GetStreamBitsRemaining() > 0)
		lclNumBits = _pCoeffTokenVlcDecoder->Decode3(pBsr, &totalCoeff, &trailingOnes, &_numTotNeighborCoeff);
	else	///< Stream is empty.
		return(STREAM_ACCESS_DENIED);
	if(lclNumBits > 0)
		totalDecBits += lclNumBits;
	else	///< Vlc error.
		return(VLC_SYMBOL_NOT_RECOGNISED);

	/// Only requires decoding if there are any non-zero coeffs.
	if(totalCoeff > 0)
	{
		int suffixLength	= 0;	///< Default and most likely case.
		if((totalCoeff > 10) && (trailingOnes < 3))	///< Special condition for spatially active blocks.
			suffixLength = 1;

		/// Extract all the non-zero coeffs that are stored in reverse order from high freq 
		/// to low freq starting with the trailing ones.
		for(i = 0; i < totalCoeff; i++)
		{
			if(i < trailingOnes)
			{
				int trailingOnesSignFlag;
				/// trailing_ones_sign_flag is parsed from the bit stream.
				if(pBsr->GetStreamBitsRemaining() > 0)
					trailingOnesSignFlag = pBsr->Read();
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				totalDecBits++;
				level[i] = 1 - 2*trailingOnesSignFlag;
			}//end if i...
			else
			{
				int levelPrefix;
				/// level_prefix is parsed from the bit stream by counting zeros.
				if(pBsr->GetStreamBitsRemaining() > 0)
					levelPrefix = _pPrefixVlcDecoder->Decode(pBsr);
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				lclNumBits = _pPrefixVlcDecoder->GetNumDecodedBits();
				if(lclNumBits > 0)
					totalDecBits += lclNumBits;
				else	///< Vlc error.
					return(VLC_SYMBOL_NOT_RECOGNISED);

				int levelSuffixSize = suffixLength;
				/// Modify the suffix bits to extract large values.
				if(levelPrefix >= 15)
					levelSuffixSize = levelPrefix - 3;
				else if((levelPrefix == 14)&&(suffixLength == 0))
					levelSuffixSize = 4;

				int levelSuffix = 0;
				if(levelSuffixSize > 0)
				{
					/// level_suffix is parsed from the bit stream.
					if(pBsr->GetStreamBitsRemaining() >= levelSuffixSize)
						levelSuffix = pBsr->Read(levelSuffixSize);
					else	///< Stream is empty.
						return(STREAM_ACCESS_DENIED);
					totalDecBits += levelSuffixSize;
				}//end if levelSuffixSize...

				/// Shift levelPrefix left into bit position defined by suffixLength
				/// and add the levelSuffix.
				int levelCode;
				if(levelPrefix < 15)
					levelCode = (levelPrefix << suffixLength) + levelSuffix;
				else
					levelCode = (15 << suffixLength) + levelSuffix;

				if((levelPrefix >= 15) && (suffixLength == 0))	///< Special condition for large high freq trailing levels.
					levelCode += 15;

				if(levelPrefix >= 16)
					levelCode += (1 << (levelPrefix-3)) - 4096;	///< Special condition for all large values.

				if((i == trailingOnes) && (trailingOnes < 3))	///< Special condition for non-ones in the trailing 3 positions.
					levelCode += 2;

				/// Translate the levelCode into the +/- level stored as even/odd codes.
				if(levelCode & 1)	///< Odd is -.
					level[i] = (-levelCode - 1) >> 1;
				else							///< Even is +.
					level[i] = (levelCode + 2) >> 1;

				/// If the level is above a threshold then increment suffixLength for next parse. Note
				/// suffixLength cannot be longer than 6 bits.
				if(suffixLength == 0)
					suffixLength = 1;
				int absLevel = level[i];
				if(absLevel < 0)
					absLevel = -absLevel;
				if((absLevel > (3 << (suffixLength-1))) && (suffixLength < 6))
					suffixLength++;
			}//end else...
		}//end for i...

		/// Get the total no. of zeros inbetween the non-zero coeffs.
		int zerosLeft = 0;
		if(totalCoeff < (_maxNumCoeff - _dcSkip))	///< i.e. there are some zeros.
		{
			/// total_zeros is parsed from the bit stream and is dependent on totalCoeff.
			if(pBsr->GetStreamBitsRemaining() > 0)
				lclNumBits = _pTotalZerosVlcDecoder->Decode2(pBsr, &zerosLeft, &totalCoeff);
			else	///< Stream is empty.
				return(STREAM_ACCESS_DENIED);
			if(lclNumBits > 0)
				totalDecBits += lclNumBits;
			else	///< Vlc error.
				return(VLC_SYMBOL_NOT_RECOGNISED);
		}//end if totalCoeff...

		/// Set the run_before values for each non-zero coeff. Note that the last
		/// (low freq) non-zero coeff run_before does not need decoding because it 
		/// is implicit.
		for(i = 0; i < (totalCoeff-1); i++)
		{
			runBefore[i] = 0;
			if(zerosLeft > 0)
			{
				/// run_before is parsed from the bit stream and is dependent on the current zerosLeft.
				if(pBsr->GetStreamBitsRemaining() > 0)
					lclNumBits = _pRunBeforeVlcDecoder->Decode2(pBsr, &(runBefore[i]), &zerosLeft);
				else	///< Stream is empty.
					return(STREAM_ACCESS_DENIED);
				if(lclNumBits > 0)
					totalDecBits += lclNumBits;
				else	///< Vlc error.
					return(VLC_SYMBOL_NOT_RECOGNISED);
			}//end if zerosLeft...
			zerosLeft -= runBefore[i];
		}//end for i...
		runBefore[totalCoeff-1] = zerosLeft;	///< Set the implicit run_before.

		/// Load the level non-zero coeffs into the output array in reverse order and
		/// with zigzag conversion. The coeff level array was initialised to zeros so
		/// only non-zero coeffs need to be added.
		int coeffNum = -1;
		for(i = (totalCoeff-1); i >= 0; i--)
		{
			coeffNum += (runBefore[i] + 1);
//			coeffLevel[_zigZag[coeffNum + _dcSkip]] = (short)(level[i]);
			coeffLevel->Write(_zigZagX[coeffNum + _dcSkip], _zigZagY[coeffNum + _dcSkip], (short)(level[i]));
		}//end for i...

	}//end if totalCoeff...

	/// Store total coeffs for this decode session.
	_numCoeff = totalCoeff;

	return(totalDecBits);
}//end Decode.

/** Set the codec mode.
The mode defines the block size choice in this implementation.
@param mode	:	Block size selection defined by class consts.
@return			: none.
*/
void CAVLCH264Impl2::SetMode(int mode)
{
	_mode = mode;
	switch(mode)
	{
		case Mode2x2:
			_zigZagX			= zigZag2x2PosX;
			_zigZagY			= zigZag2x2PosY;
			_maxNumCoeff	= 4;
			break;
		case Mode4x4:
			_zigZagX			= zigZag4x4PosX;
			_zigZagY			= zigZag4x4PosY;
			_maxNumCoeff	= 16;
			break;
		case Mode8x8:
			_zigZagX			= zigZag8x8PosX;
			_zigZagY			= zigZag8x8PosY;
			_maxNumCoeff	= 64;
			break;
		default:
			_mode					= Mode4x4;
			_zigZagX			= zigZag4x4PosX;
			_zigZagY			= zigZag4x4PosY;
			_maxNumCoeff	= 16;
			break;
	}//end switch mode...
}//end SetMode.

/** Set the codec parameters.
The IDs are defined by the class consts and values by the 
members. Do nothing if the param is not defined in this 
implementation.
@param paramID	: Parameter to set.
@param paramVal	: Parameter value.
@return					: none.
*/
void CAVLCH264Impl2::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case NUM_TOT_NEIGHBOR_COEFF_ID:
			_numTotNeighborCoeff = paramVal;
			break;
		case DC_SKIP_FLAG_ID:
			_dcSkip = paramVal;
			break;
	}//end switch paramID...
}//end SetParameter.

/** Get the codec parameters.
Return -1 if the param is not defined in this implementation.
@param paramID	: Parameter to get.
@return					: Param value.
*/
int CAVLCH264Impl2::GetParameter(int paramID)
{
	int res = -1;
	switch(paramID)
	{
		case NUM_TOT_NEIGHBOR_COEFF_ID:
			res = _numTotNeighborCoeff;
			break;
		case DC_SKIP_FLAG_ID:
			res = _dcSkip;
			break;
		case NUM_TOT_COEFF_ID:
			res = _numCoeff;
			break;
	}//end switch paramID...

	return(res);
}//end GetParameter.

========== END FILE: CodecUtils/CAVLCH264Impl2.cpp ==========

========== BEGIN FILE: CodecUtils/CAVLCH264Impl2.h ==========
Bundle entry: 13
Original bytes: 6051
Original SHA-256: f6cd83103d88ad65d241bf44f269e297e46862b963d963eb68f5b5fb596b0e3f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CAVLCH264Impl2

TAG						: CAVLCH264I2

FILE NAME			: CAVLCH264Impl2.h

DESCRIPTION		: A class to implement a CAVLC codec on the 2-D quantised 
								integer transformed and quantised coeffs of a coded block 
								as defined in the H.264 standard. It implements the 
								IContextAwareRunLevelCodec interface. This 2nd implementation 
                operates on OverlayMem2Dv2 classes and not on the data directly.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _CAVLCH264IMPL2_H
#define _CAVLCH264IMPL2_H

#pragma once

#include "IContextAwareRunLevelCodec.h"
#include "IVlcEncoder.h"
#include "IVlcDecoder.h"
#include "OverlayMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CAVLCH264Impl2 : public IContextAwareRunLevelCodec
{
public:
	CAVLCH264Impl2(void);
	virtual ~CAVLCH264Impl2(void);

/// Interface implementation.
public:
	/** Encode the input to a CAVLC bit stream.
	Encode the input 2-D block of IT coeffs into the output 
	run-level bit stream.
	@param in		:	Input block overlay to encode.
	@param rle	:	Run-level encoded stream.
	@return			: Total num of encoded bits. Negative values for errors.
	*/
	int Encode(void* in, void* stream);

	/** Decode a CAVLC bit stream to the output.
	Decode the input run-level bit stream into the
	output 2-D block of IT coeffs.
	@param stream	:	Run-level stream to decode.
	@param out		:	Output block overlay generated by the decode.
	@return				: Total num of decoded bits. Negative values for errors.
	*/
	int Decode(void* stream, void* out);

	void	SetMode(int mode);
	int		GetMode(void)			{ return(_mode); }

	void	SetParameter(int paramID, int paramVal);
	int		GetParameter(int paramID);

/// Implementation specific methods.
public:
	/// Vlc encoders and decoders are used by (associated with) this class and
	/// are required to be set up before encoding/decoding takes place.

	/** Set vlc encoder/decoder to use.
	@param	vlc	: Vlc encoder reference.
	@return			: None.
	*/
	void SetTokenCoeffVlcEncoder(IVlcEncoder* vlc)	{ _pCoeffTokenVlcEncoder = vlc; }
	void SetTokenCoeffVlcDecoder(IVlcDecoder* vlc)	{ _pCoeffTokenVlcDecoder = vlc; }
	void SetPrefixVlcEncoder(IVlcEncoder* vlc)			{ _pPrefixVlcEncoder = vlc; }
	void SetPrefixVlcDecoder(IVlcDecoder* vlc)			{ _pPrefixVlcDecoder = vlc; }
	void SetTotalZerosVlcEncoder(IVlcEncoder* vlc)	{ _pTotalZerosVlcEncoder = vlc; }
	void SetTotalZerosVlcDecoder(IVlcDecoder* vlc)	{ _pTotalZerosVlcDecoder = vlc; }
	void SetRunBeforeVlcEncoder(IVlcEncoder* vlc)		{ _pRunBeforeVlcEncoder = vlc; }
	void SetRunBeforeVlcDecoder(IVlcDecoder* vlc)		{ _pRunBeforeVlcDecoder = vlc; }

/// Class constants.
protected:
	static const int zigZag8x8PosX[64];
	static const int zigZag8x8PosY[64];
	static const int zigZag4x4PosX[16];
	static const int zigZag4x4PosY[16];
	static const int zigZag2x2PosX[4];
	static const int zigZag2x2PosY[4];

public:
	static const int VLC_SYMBOL_NOT_RECOGNISED	= -1;
	static const int STREAM_ACCESS_DENIED				= -2; ///< Full for write & Empty for read.

	/// Class members.
protected:
	const int*	_zigZagX;			///< Active selection of const arrays.
	const int*	_zigZagY;			///< Active selection of const arrays.
	int					_mode;				///< Active mode.
	int					_maxNumCoeff;	///< Num of coeffs in block e.g. 4x4 = 16.
	int					_numCoeff;		///< After encoding or decoding store the no. of coeff for this block.

	/// Parameters for this class for each param ID.
	int					_numTotNeighborCoeff;	///< VLC table selection is based on total coeffs of neighbors.
	int					_dcSkip;							///< All run length coding must ignore the DC coeff in position zero.

	/// Associated Vlc encoders/decoders.
	IVlcEncoder*	_pCoeffTokenVlcEncoder;
	IVlcDecoder*	_pCoeffTokenVlcDecoder;
	IVlcEncoder*	_pPrefixVlcEncoder;
	IVlcDecoder*	_pPrefixVlcDecoder;
	IVlcEncoder*	_pTotalZerosVlcEncoder;
	IVlcDecoder*	_pTotalZerosVlcDecoder;
	IVlcEncoder*	_pRunBeforeVlcEncoder;
	IVlcDecoder*	_pRunBeforeVlcDecoder;

};// end class CAVLCH264Impl2.

#endif	//_CAVLCH264IMPL2_H
========== END FILE: CodecUtils/CAVLCH264Impl2.h ==========

========== BEGIN FILE: CodecUtils/CodecConfigurationUtil.h ==========
Bundle entry: 14
Original bytes: 6181
Original SHA-256: 32373c622ab5149eeb6a66d74993c5c4c32d8396e718f765a5c64a9d5679316e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE:
 
TAG: 

FILE NAME: 

DESCRIPTION: 

COPYRIGHT: (c)CSIR 2007-2018 all rights reserved

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#pragma once
#include <cstdint>
#include "Codecs/CodecUtils/ICodecv2.h"
#include "CodecParameters.h"

/**
 * @brief Utility method to configure the RTCV H264 codec with default parameters
 */
static bool configureDefaultH263CodecParameters(ICodecv2* pCodec)
{
  if (!pCodec) return false;
  //Used for setting fixed size frame allocation
  pCodec->SetParameter(CODEC_PARAM_MODE_OF_OPERATION, "2");
  //Set default quality to 16
  pCodec->SetParameter(CODEC_PARAM_QUALITY, "1");
  //16 = YUV
  pCodec->SetParameter(CODEC_PARAM_IN_COLOUR, "16");
  //16 = YUV
  pCodec->SetParameter(CODEC_PARAM_OUT_COLOUR, "16");
  // This multiplies the bit size of every i-frame by 2
  pCodec->SetParameter(CODEC_PARAM_I_PICTURE_MULTIPLIER, "2");
  // Use a switch frame period of ten for now
  pCodec->SetParameter(CODEC_PARAM_SWITCH_FRAME_PERIOD, "10");
  // NB: New codec settings for auto-iframe detection: These settings need to correlate to the settings of the DECODER
  pCodec->SetParameter("unrestrictedmotion", "1");
  pCodec->SetParameter("extendedpicturetype", "1");
  pCodec->SetParameter("unrestrictedmotion", "1");
  pCodec->SetParameter("advancedintracoding", "1");
  pCodec->SetParameter("alternativeintervlc", "1");
  pCodec->SetParameter("modifiedquant", "1");
  pCodec->SetParameter("autoipicture", "1");
  pCodec->SetParameter("ipicturefraction", "0");
  // On Windows we will always flip the color-converted image
  pCodec->SetParameter("flip", "1");

  return true;
}

/**
 * @brief Utility method to configure the RTCV H264 codec with default parameters
 */
static bool configureDefaultH264CodecParameters(ICodecv2* pCodec)
{
  if (!pCodec) return false;
  //Set default quality to 16
  pCodec->SetParameter(CODEC_PARAM_QUALITY, "1");
  //16 = YUV
  pCodec->SetParameter(CODEC_PARAM_IN_COLOUR, "16");
  //16 = YUV
  pCodec->SetParameter(CODEC_PARAM_OUT_COLOUR, "16");
  // This multiplies the bit size of every i-frame by 2
  pCodec->SetParameter(CODEC_PARAM_I_PICTURE_MULTIPLIER, "1");

  pCodec->SetParameter(CODEC_PARAM_SWITCH_FRAME_PERIOD, "12");

  // default rate control values
  pCodec->SetParameter(CODEC_PARAM_MAX_BITS_PER_FRAME, "1000000");
  pCodec->SetParameter(CODEC_PARAM_NUM_RATE_CONTROL_FRAMES, "25");
  pCodec->SetParameter(CODEC_PARAM_MAX_DISTORTION, "30000");
  pCodec->SetParameter(CODEC_PARAM_IPICTURE_DMAX_MULTIPLIER, "2");
  pCodec->SetParameter(CODEC_PARAM_IPICTURE_DMAX_FRACTION, "0");
  pCodec->SetParameter(CODEC_PARAM_MINIMUM_INTRA_QP, "16");
  pCodec->SetParameter(CODEC_PARAM_MINIMUM_INTER_QP, "4");
  pCodec->SetParameter(CODEC_PARAM_RATE_OVERSHOOT_PERCENT, "100");

  // always flip the image on windows to get it into the desired YUV format
  pCodec->SetParameter("flip", "1");
  // NB: New codec settings for auto-iframe detection: These settings need to correlate to the settings of the DECODER
  pCodec->SetParameter("unrestrictedmotion", "1");
  pCodec->SetParameter("extendedpicturetype", "1");
  pCodec->SetParameter("unrestrictedmotion", "1");
  pCodec->SetParameter("advancedintracoding", "1");
  pCodec->SetParameter("alternativeintervlc", "1");
  pCodec->SetParameter("modifiedquant", "1");
  pCodec->SetParameter("autoipicture", "1");
  pCodec->SetParameter("ipicturefraction", "0");

  return true;
}

/**
 * @brief utility method to generate parameter sets
 */
bool generateParameterSets(ICodecv2* pCodec, std::string& sSps, std::string& sPps)
{
  uint8_t pBuffer[512];

  pCodec->SetParameter((char *)"seq param set", "0");
  pCodec->SetParameter((char *)"pic param set", "0");

  pCodec->SetParameter((char *)("generate param set on open"), "0");
  pCodec->SetParameter((char *)("picture coding type"), "2");	///< Seq param set = H264V2_SEQ_PARAM.
  if (!pCodec->Code(NULL, pBuffer, 512 * 8))
  {
    return false;
  }
  else
  {
    uint32_t uiSeqParamSetLen = pCodec->GetCompressedByteLength();
    pBuffer[uiSeqParamSetLen] = 0;
    sSps = std::string((const char*)pBuffer, uiSeqParamSetLen);
  }

  pCodec->SetParameter((char *)("picture coding type"), "3");	///< Pic param set = H264V2_PIC_PARAM.
  if (!pCodec->Code(NULL, pBuffer, 512 * 8))
  {
    return false;
  }
  else
  {
    uint32_t uiPicParamSetLen = pCodec->GetCompressedByteLength();
    pBuffer[uiPicParamSetLen] = 0;
    sPps = std::string((const char*)pBuffer, uiPicParamSetLen);
  }
  return true;
}


========== END FILE: CodecUtils/CodecConfigurationUtil.h ==========

========== BEGIN FILE: CodecUtils/CodecDistortionDef.h ==========
Bundle entry: 15
Original bytes: 2556
Original SHA-256: b442bc78a25fbb223f9d22f5dbe156bb670b14c98381fa6adf87c10ffdeac6b0
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodecDistortionDef

TAG						: CDD

FILE NAME			: CodecDistortionDef.h

DESCRIPTION		: A class to define with a macro the distortion metric used in codecs.

COPYRIGHT			: (c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/

#ifndef _CODECDISTORTIONDEF_H
#define _CODECDISTORTIONDEF_H

#pragma once

#include <math.h>
#include <stdlib.h>

#define DISTORTIONABSDIFF(x,y) ( abs((x)-(y)) )
#define DISTORTIONSQRDIFF(x,y) ( ((x)-(y))*((x)-(y)) )

#undef USE_ABSOLUTE_DIFFERENCE
//#define USE_ABSOLUTE_DIFFERENCE 1

/// DISTORTION params x = original y = distorted
#ifdef USE_ABSOLUTE_DIFFERENCE
#define DISTORTION(x,y) ( DISTORTIONABSDIFF((x),(y)) )
#else
#define DISTORTION(x,y) ( DISTORTIONSQRDIFF((x),(y)) )
#endif

#endif	// _CODECDISTORTIONDEF_H
========== END FILE: CodecUtils/CodecDistortionDef.h ==========

========== BEGIN FILE: CodecUtils/CodecParameters.h ==========
Bundle entry: 16
Original bytes: 3028
Original SHA-256: 48d23eb03880d0d3d7a601236a31c6b05d7bd76e9f4064097ab255239d961e0e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE:
 
TAG: 

FILE NAME: 

DESCRIPTION: 

COPYRIGHT: (c)CSIR 2007-2018 all rights reserved

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================

*/
#pragma once
// H263/H264-specific codec parameters
#define CODEC_PARAM_IN_COLOUR                 "incolour"
#define CODEC_PARAM_OUT_COLOUR                "outcolour"
#define CODEC_PARAM_MODE_OF_OPERATION         "mode of operation"
#define CODEC_PARAM_FRAME_BIT_LIMIT           "framebitlimit"	
#define CODEC_PARAM_NOTIFYONIFRAME            "notifyoniframe"
#define CODEC_PARAM_SWITCH_FRAME_PERIOD       "switchframeperiod"
#define	CODEC_PARAM_I_PICTURE_MULTIPLIER      "ipicturemultiplier"
#define	CODEC_PARAM_AUTO_IFRAME_DETECT_FLAG   "autoiframedetectflag"
#define CODEC_PARAM_IFRAME_PERIOD             "iframeperiod"
#define CODEC_PARAM_QUALITY                   "quality"
// Rate control-related parameters
#define CODEC_PARAM_RATE_CONTROL_MODEL_TYPE   "rate control model type"
#define CODEC_PARAM_MAX_BITS_PER_FRAME        "max bits per frame"
#define CODEC_PARAM_NUM_RATE_CONTROL_FRAMES   "num rate control frames"
#define CODEC_PARAM_MAX_DISTORTION            "max distortion"
#define CODEC_PARAM_IPICTURE_DMAX_MULTIPLIER  "ipicture dmax multiplier"
#define CODEC_PARAM_IPICTURE_DMAX_FRACTION    "ipicture dmax fraction"
#define CODEC_PARAM_MINIMUM_INTRA_QP          "minimum intra qp"
#define CODEC_PARAM_MINIMUM_INTER_QP          "minimum inter qp"
#define CODEC_PARAM_RATE_OVERSHOOT_PERCENT    "rate overshoot percent"

========== END FILE: CodecUtils/CodecParameters.h ==========

========== BEGIN FILE: CodecUtils/CodedBlkPatternH264VlcDecoder.cpp ==========
Bundle entry: 17
Original bytes: 5057
Original SHA-256: 0465808168eb95cdd1f0bc1580ec533422e2bde59ad70105bd731fa522c3ebcd
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodedBlkPatternH264VlcDecoder

TAG						: CBPH264VD

FILE NAME			: CodedBlkPatternH264VlcDecoder.cpp

DESCRIPTION		: A coded block pattern Vlc decoder implementation used in 
								H.264 Recommendation (03/2005)Table 9.4(a) on page 196. 
								This implementation is implemented with an IVlcDecoder 
								Interface and is an extention of the unsigned Exp-Golomb 
								Vlc decoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "CodedBlkPatternH264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
CodedBlkPatternH264VlcDecoder::CodedBlkPatternH264VlcDecoder(void)
{
}//end constructor.

CodedBlkPatternH264VlcDecoder::~CodedBlkPatternH264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode with a macroblock type
The 2 symbols represent the returned coded block pattern value and the 
macroblock prediction mode (Intra/Inter) is used as an input, respectively.
@param bsr			: Bit stream to get from.
@param symbol1	: Block pattern decoded.
@param symbol2	: Intra/inter = 0/1.
@return					: Num of bits extracted.
*/
int	CodedBlkPatternH264VlcDecoder::Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
{
	/// Reset bits extracted.
  _numCodeBits = 0;

	int code = ExpGolombUnsignedVlcDecoder::Decode(bsr);	///< _numCodeBits is updated in the base class.

	if(code < 48)	///< In the range of the tables.
	{
		if(*symbol2)	///< if Inter...
			*symbol1 = InterTable[code];
		else
			*symbol1 = IntraTable[code];
	}//end if code...

  return(_numCodeBits);
}//end Decode2.

/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const int CodedBlkPatternH264VlcDecoder::IntraTable[48] =
{	///< 0		1		2		3		4		5		6		7
	    47,  31, 15,  0, 23, 27, 29, 30,
	///< 8		9	 10	 11	 12  13  14  15
	     7,  11, 13, 14, 39, 43, 45, 46,
	///<16   17  18  19  20  21  22  23
	    16,   3,  5, 10, 12, 19, 21, 26,
	///<24   25  26  27  28  29  30  31
	    28,  35, 37, 42, 44,  1,  2,  4,
	///<32   33  34  35  36  37  38  39
	     8,  17, 18, 20, 24,  6,  9, 22,
	///<40   41  42  43  44  45  46  47
	    25,  32, 33, 34, 36, 40, 38, 41
};

const int CodedBlkPatternH264VlcDecoder::InterTable[48] = 
{	///< 0		1		2		3		4		5		6		7
	     0,  16,  1,  2,  4,  8, 32,  3,
	///< 8		9	 10	 11	 12  13  14  15
	     5,  10, 12, 15, 47,  7, 11, 13,
	///<16   17  18  19  20  21  22  23
	    14,   6,  9, 31, 35, 37, 42, 44,
	///<24   25  26  27  28  29  30  31
	    33,  34, 36, 40, 39, 43, 45, 46,
	///<32   33  34  35  36  37  38  39
	    17,  18, 20, 24, 19, 21, 26, 28,
	///<40   41  42  43  44  45  46  47
	    23,  27, 29, 30, 22, 25, 38, 41
};

========== END FILE: CodecUtils/CodedBlkPatternH264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/CodedBlkPatternH264VlcDecoder.h ==========
Bundle entry: 18
Original bytes: 3537
Original SHA-256: cf21e6241ff8296407854969393bd9ed06b106bdbafb6f8b7c7ac5b8bb9541d7
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodedBlkPatternH264VlcDecoder

TAG						: CBPH264VD

FILE NAME			: CodedBlkPatternH264VlcDecoder.h

DESCRIPTION		: A coded block pattern Vlc decoder implementation used in 
								H.264 Recommendation (03/2005)Table 9.4(a) on page 196. 
								This implementation is implemented with an IVlcDecoder 
								Interface and is an extention of the unsigned Exp-Golomb 
								Vlc decoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _CODEDBLKPATTERNH264VLCDECODER_H
#define _CODEDBLKPATTERNH264VLCDECODER_H

#include "ExpGolombUnsignedVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CodedBlkPatternH264VlcDecoder : public ExpGolombUnsignedVlcDecoder
{
public:
	CodedBlkPatternH264VlcDecoder(void);
	virtual ~CodedBlkPatternH264VlcDecoder(void);

public:
	/// There is no single symbol decoding requirement.
	virtual int Decode(IBitStreamReader* bsr) { return(0); }

	/// Optional interface.
public:

	/** Decode with a macroblock type
	The 2 symbols represent the returned coded block pattern value and the 
	macroblock prediction mode (Intra/Inter) is used as an input, respectively.
	@param bsr			: Bit stream to get from.
	@param symbol1	: Block pattern decoded.
	@param symbol2	: Intra/inter = 0/1.
	@return					: Num of bits extracted.
	*/
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2);

protected:
	/// Constants of table sets.
	static const int IntraTable[48];
	static const int InterTable[48];

};// end class CodedBlkPatternH264VlcDecoder.

#endif	// end _CODEDBLKPATTERNH264VLCDECODER_H.
========== END FILE: CodecUtils/CodedBlkPatternH264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/CodedBlkPatternH264VlcEncoder.cpp ==========
Bundle entry: 19
Original bytes: 4898
Original SHA-256: fe63c0758b792f8ee0b49f1ff3159a64ed5dd9d0e035b363f66c462f45419fa0
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodedBlkPatternH264VlcEncoder

TAG						: CBPH264VE

FILE NAME			: CodedBlkPatternH264VlcEncoder.cpp

DESCRIPTION		: A coded block pattern Vlc encoder implementation used in 
								H.264 Recommendation (03/2005)Table 9.4(a) on page 196. 
								This implementation is implemented with an IVlcEncoder 
								Interface and is an extention of the unsigned Exp-Golomb 
								Vlc encoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "CodedBlkPatternH264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
CodedBlkPatternH264VlcEncoder::CodedBlkPatternH264VlcEncoder(void)
{
}//end constructor.

CodedBlkPatternH264VlcEncoder::~CodedBlkPatternH264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode with a macroblock type
The 2 symbols represent the coded block pattern value and the 
macroblock prediction mode (Intra/Inter), respectively.
@param symbol1	: Block pattern to encode.
@param symbol2	: Intra/inter = 0/1.
@return					: Num of bits in the codeword.
*/
int	CodedBlkPatternH264VlcEncoder::Encode2(int symbol1, int symbol2)
{
	_bitCode			= 0;
	_numCodeBits	= 0;
	if(symbol1 < 48)
	{
		int code = 0;
		if(symbol2)	///< if Inter...
			code = InterTable[symbol1];
		else
			code = IntraTable[symbol1];

		return(ExpGolombUnsignedVlcEncoder::Encode(code));
	}//end if symbol1...

	return(_numCodeBits);
}//end Encode2.

/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const int CodedBlkPatternH264VlcEncoder::IntraTable[48] =
{	///< 0		1		2		3		4		5		6		7
	     3,  29, 30, 17, 31, 18, 37,  8,
	///< 8		9	 10	 11	 12  13  14  15
	    32,  38, 19,  9, 20, 10, 11,  2,
	///<16   17  18  19  20  21  22  23
	    16,  33, 34, 21, 35, 22, 39,  4,
	///<24   25  26  27  28  29  30  31
	    36,  40, 23,  5, 24,  6,  7,  1,
	///<32   33  34  35  36  37  38  39
	    41,  42, 43, 25, 44, 26, 46, 12,
	///<40   41  42  43  44  45  46  47
	    45,  47, 27, 13, 28, 14, 15,  0
};

const int CodedBlkPatternH264VlcEncoder::InterTable[48] = 
{	///< 0		1		2		3		4		5		6		7
			 0,		2,	3,	7,	4,	8, 17, 13,
	///< 8		9	 10	 11	 12  13  14  15
			 5,  18,  9, 14, 10, 15, 16, 11,
	///<16   17  18  19  20  21  22  23
		   1,  32, 33, 36, 34, 37, 44, 40,
	///<24   25  26  27  28  29  30  31
	    35,  45, 38, 41, 39, 42, 43, 19,
	///<32   33  34  35  36  37  38  39
	     6,  24, 25, 20, 26, 21, 46, 28,
	///<40   41  42  43  44  45  46  47
		  27,  47, 22, 29, 23, 30, 31, 12
};



========== END FILE: CodecUtils/CodedBlkPatternH264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/CodedBlkPatternH264VlcEncoder.h ==========
Bundle entry: 20
Original bytes: 3443
Original SHA-256: 112129b615b29452d1a6dd38ffbfbe10e1b0b469d6f94bedf179b7bd53d78413
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodedBlkPatternH264VlcEncoder

TAG						: CBPH264VE

FILE NAME			: CodedBlkPatternH264VlcEncoder.h

DESCRIPTION		: A coded block pattern Vlc encoder implementation used in 
								H.264 Recommendation (03/2005)Table 9.4(a) on page 196. 
								This implementation is implemented with an IVlcEncoder 
								Interface and is an extention of the unsigned Exp-Golomb 
								Vlc encoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _CODEDBLKPATTERNH264VLCENCODER_H
#define _CODEDBLKPATTERNH264VLCENCODER_H

#include "ExpGolombUnsignedVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CodedBlkPatternH264VlcEncoder : public ExpGolombUnsignedVlcEncoder
{
public:
	CodedBlkPatternH264VlcEncoder(void);
	virtual ~CodedBlkPatternH264VlcEncoder(void);

public:
	/// Does not have a single symbol encoding requirement.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface.
public:

	/** Encode with a macroblock type
	The 2 symbols represent the coded block pattern value and the 
	macroblock prediction mode (Intra/Inter), respectively.
	@param symbol1	: Block pattern to encode.
	@param symbol2	: Intra/inter = 0/1.
	@return					: Num of bits in the codeword.
	*/
	virtual int	Encode2(int symbol1, int symbol2);

protected:
	/// Constants of table sets.
	static const int IntraTable[48];
	static const int InterTable[48];

};// end class CodedBlkPatternH264VlcEncoder.

#endif	// end _CODEDBLKPATTERNH264VLCENCODER_H.
========== END FILE: CodecUtils/CodedBlkPatternH264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/CodeFragmentForH264BlockLayerTest.cpp ==========
Bundle entry: 21
Original bytes: 35987
Original SHA-256: 3b2b489bc476058f28682aeb11f08251bf65aa8e2e982e3fcfc650c8f810c649
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CodeFragmentForH264BlockLayerTest

TAG						: CFH264BLT

FILE NAME			: CodeFragmentForH264BlockLayerTest.cpp

DESCRIPTION		: A code fragment of the unit tests for the CAVLC codec and the
								H.264 block layer defined in ITU-T Rec. H.264 (03/2005). This
								will not compile as all #include header files are excluded.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/

/// There are two test functions defined in this fragment.
/// TestCAVLC() and TestBlockLayer().

/** Test CAVLC.
@return	: 1 = success, 0 = failed..
*/
#define H264V2C_BYTESIZE 4096
int H264v2Codec::TestCAVLC(void)
{
	int i,j,k;
	int TESTS = 4096;
	int result = 1;
	short a[16] = { 0, 3,-1, 0, 
									0,-1, 1, 0,
									1, 0, 0, 0,
									0, 0, 0, 0};
	short b[16];

	/// Use a bit stream reader/writer.
	int bitSize = H264V2C_BYTESIZE * 8;
	unsigned char stream[H264V2C_BYTESIZE];
	IBitStreamWriter* pBsw = new BitStreamWriterMSB();
	pBsw->SetStream((void *)stream, bitSize);
	IBitStreamReader* pBsr = new BitStreamReaderMSB();
	pBsr->SetStream((void *)stream, bitSize);

	/// Test the associated Vlc encoders & decoders used in CAVLC.

	/// 1. Prefix encoding & decoding.
	IVlcEncoder*	pPrefixVlcEnc = new PrefixH264VlcEncoderImpl1();
	IVlcDecoder*	pPrefixVlcDec = new PrefixH264VlcDecoderImpl1();
	for( i = 0; i < 32; i++)	///< Encode.
	{
		int numCodedBits = pPrefixVlcEnc->Encode(i);
		pBsw->Write(numCodedBits, pPrefixVlcEnc->GetCode());
	}//end for i...
	for( i = 0; i < 32; i++)	///< Decode.
	{
		int code = pPrefixVlcDec->Decode(pBsr);
		if(code != i)
			result = 0;
	}//end for i...

	/// 2. Coeff Token encoding & decoding.
	IVlcEncoder*	pCoeffTokenVlcEnc = new CoeffTokenH264VlcEncoder();
	IVlcDecoder*	pCoeffTokenVlcDec = new CoeffTokenH264VlcDecoder();
	int nC, tO, tC;
	pBsw->Reset();
	for(nC = 0; nC <= 9; nC++)	///< Encode.
	{
		for(tO = 0; tO <= 3; tO++)
		{
			for(tC = tO; tC <= 16; tC++)
			{
				int numCodedBits = pCoeffTokenVlcEnc->Encode3(tC, tO, nC);
				pBsw->Write(numCodedBits, pCoeffTokenVlcEnc->GetCode());
			}//end for tC...
		}//end for tO...
	}//end for nC...
	nC = -1;
	for(tO = 0; tO <= 3; tO++)
	{
		for(tC = tO; tC <= 4; tC++)
		{
			int numCodedBits = pCoeffTokenVlcEnc->Encode3(tC, tO, nC);
			pBsw->Write(numCodedBits, pCoeffTokenVlcEnc->GetCode());
		}//end for tC...
	}//end for tO...
	nC = -2;
	for(tO = 0; tO <= 3; tO++)
	{
		for(tC = tO; tC <= 8; tC++)
		{
			int numCodedBits = pCoeffTokenVlcEnc->Encode3(tC, tO, nC);
			pBsw->Write(numCodedBits, pCoeffTokenVlcEnc->GetCode());
		}//end for tC...
	}//end for tO...

	pBsr->Reset();
	for(nC = 0; nC <= 9; nC++)	///< Decode.
	{
		for(tO = 0; tO <= 3; tO++)
		{
			for(tC = tO; tC <= 16; tC++)
			{
				int trailingOnes	= 0;
				int totalCoeffs		= 0;
				int numCodedBits = pCoeffTokenVlcDec->Decode3(pBsr, &totalCoeffs, &trailingOnes, &nC);
				if( (tC != totalCoeffs)||(tO != trailingOnes) )
					result = 0;
			}//end for tC...
		}//end for tO...
	}//end for nC...
	nC = -1;
	for(tO = 0; tO <= 3; tO++)
	{
		for(tC = tO; tC <= 4; tC++)
		{
			int trailingOnes	= 0;
			int totalCoeffs		= 0;
			int numCodedBits = pCoeffTokenVlcDec->Decode3(pBsr, &totalCoeffs, &trailingOnes, &nC);
			if( (tC != totalCoeffs)||(tO != trailingOnes) )
				result = 0;
		}//end for tC...
	}//end for tO...
	nC = -2;
	for(tO = 0; tO <= 3; tO++)
	{
		for(tC = tO; tC <= 8; tC++)
		{
			int trailingOnes	= 0;
			int totalCoeffs		= 0;
			int numCodedBits = pCoeffTokenVlcDec->Decode3(pBsr, &totalCoeffs, &trailingOnes, &nC);
			if( (tC != totalCoeffs)||(tO != trailingOnes) )
				result = 0;
		}//end for tC...
	}//end for tO...

	/// 3. Total Zeros encoding & decoding.
	IVlcEncoder*	pTotalZeros4x4VlcEnc = new TotalZeros4x4H264VlcEncoder();
	IVlcDecoder*	pTotalZeros4x4VlcDec = new TotalZeros4x4H264VlcDecoder();
	int tZ;
	pBsw->Reset();
	for(tC = 1; tC <= 15; tC++)	///< Encode.
	{
		for(tZ = 0; tZ <= (16-tC); tZ++)
		{
			int numCodedBits = pTotalZeros4x4VlcEnc->Encode2(tZ, tC);
			pBsw->Write(numCodedBits, pTotalZeros4x4VlcEnc->GetCode());
		}//end for tZ...
	}//end for tC...

	pBsr->Reset();
	for(tC = 1; tC <= 15; tC++)	///< Decode.
	{
		for(tZ = 0; tZ <= (16-tC); tZ++)
		{
			int totalZeros = 0;
			int numCodedBits = pTotalZeros4x4VlcDec->Decode2(pBsr, &totalZeros, &tC);
			if(totalZeros != tZ)
				result = 0;
		}//end for tZ...
	}//end for tC...

	IVlcEncoder*	pTotalZeros2x2VlcEnc = new TotalZeros2x2H264VlcEncoder();
	IVlcDecoder*	pTotalZeros2x2VlcDec = new TotalZeros2x2H264VlcDecoder();
	pBsw->Reset();
	for(tC = 1; tC <= 3; tC++)	///< Encode.
	{
		for(tZ = 0; tZ <= (4-tC); tZ++)
		{
			int numCodedBits = pTotalZeros2x2VlcEnc->Encode2(tZ, tC);
			pBsw->Write(numCodedBits, pTotalZeros2x2VlcEnc->GetCode());
		}//end for tZ...
	}//end for tC...

	pBsr->Reset();
	for(tC = 1; tC <= 3; tC++)	///< Decode.
	{
		for(tZ = 0; tZ <= (4-tC); tZ++)
		{
			int totalZeros = 0;
			int numCodedBits = pTotalZeros2x2VlcDec->Decode2(pBsr, &totalZeros, &tC);
			if(totalZeros != tZ)
				result = 0;
		}//end for tZ...
	}//end for tC...

	IVlcEncoder*	pTotalZeros2x4VlcEnc = new TotalZeros2x4H264VlcEncoder();
	IVlcDecoder*	pTotalZeros2x4VlcDec = new TotalZeros2x4H264VlcDecoder();
	pBsw->Reset();
	for(tC = 1; tC <= 7; tC++)	///< Encode.
	{
		for(tZ = 0; tZ <= (8-tC); tZ++)
		{
			int numCodedBits = pTotalZeros2x4VlcEnc->Encode2(tZ, tC);
			pBsw->Write(numCodedBits, pTotalZeros2x4VlcEnc->GetCode());
		}//end for tZ...
	}//end for tC...

	pBsr->Reset();
	for(tC = 1; tC <= 7; tC++)	///< Decode.
	{
		for(tZ = 0; tZ <= (8-tC); tZ++)
		{
			int totalZeros = 0;
			int numCodedBits = pTotalZeros2x4VlcDec->Decode2(pBsr, &totalZeros, &tC);
			if(totalZeros != tZ)
				result = 0;
		}//end for tZ...
	}//end for tC...

	/// 4. Run-before encoding & decoding.
	IVlcEncoder*	pRunBeforeVlcEnc = new RunBeforeH264VlcEncoder();
	IVlcDecoder*	pRunBeforeVlcDec = new RunBeforeH264VlcDecoder();
	int rB, zL;
	pBsw->Reset();
	for(zL = 1; zL <= 14; zL++)	///< Encode.
	{
		for(rB = 0; rB <= zL; rB++)
		{
			int numCodedBits = pRunBeforeVlcEnc->Encode2(rB, zL);
			pBsw->Write(numCodedBits, pRunBeforeVlcEnc->GetCode());
		}//end for rB...
	}//end for zL...

	pBsr->Reset();
	for(zL = 1; zL <= 14; zL++)	///< Decode.
	{
		for(rB = 0; rB <= zL; rB++)
		{
			int runBefore = 0;
			int numCodedBits = pRunBeforeVlcDec->Decode2(pBsr, &runBefore, &zL);
			if(runBefore != rB)
				result = 0;
		}//end for rB...
	}//end for zL...


	/// Test the CAVLC encoding & decoding.

	/// All vlc encoders and decoders are tested. Now load them into the 
	/// CAVLC for usage in this test proceedure.
	IContextAwareRunLevelCodec* pCAVLC = new CAVLCH264Impl();
	/// Design unit test during development.
	result = CAVLCH264Impl::TestLevelPrefixSuffix();

	/// Testing for 4x4 and 2x2 modes.
	int mode;
	/// Vlc settings for all modes.
	((CAVLCH264Impl *)pCAVLC)->SetTokenCoeffVlcEncoder(pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)pCAVLC)->SetTokenCoeffVlcDecoder(pCoeffTokenVlcDec);
	((CAVLCH264Impl *)pCAVLC)->SetPrefixVlcEncoder(pPrefixVlcEnc);
	((CAVLCH264Impl *)pCAVLC)->SetPrefixVlcDecoder(pPrefixVlcDec);
	((CAVLCH264Impl *)pCAVLC)->SetRunBeforeVlcEncoder(pRunBeforeVlcEnc);
	((CAVLCH264Impl *)pCAVLC)->SetRunBeforeVlcDecoder(pRunBeforeVlcDec);

	int totNumCoeffs = 16;	///< Default value.
	for(mode = CAVLCH264Impl::Mode2x2; mode <= CAVLCH264Impl::Mode4x4; mode++)
	{
		if(mode == CAVLCH264Impl::Mode2x2)
		{
			totNumCoeffs = 4;
			pCAVLC->SetMode(CAVLCH264Impl::Mode2x2);
			((CAVLCH264Impl *)pCAVLC)->SetTotalZerosVlcEncoder(pTotalZeros2x2VlcEnc);
			((CAVLCH264Impl *)pCAVLC)->SetTotalZerosVlcDecoder(pTotalZeros2x2VlcDec);
		}//end if mode...
		else if(mode == CAVLCH264Impl::Mode4x4)
		{
			totNumCoeffs = 16;
			pCAVLC->SetMode(CAVLCH264Impl::Mode4x4);
			((CAVLCH264Impl *)pCAVLC)->SetTotalZerosVlcEncoder(pTotalZeros4x4VlcEnc);
			((CAVLCH264Impl *)pCAVLC)->SetTotalZerosVlcDecoder(pTotalZeros4x4VlcDec);
		}//end else if mode...

		for(k = 0; k < TESTS; k++)
		{
			/// Load the test samples.
			int existingZeros = 0;
			for(i = 0; i < totNumCoeffs; i++)
			{
				b[i] = 0;	///< Clear the decoded to block.
				a[i] = (short)( (((double)rand()/(double)RAND_MAX) * 1023.0) - 256.0 + 0.5 );
				if(i != 0)
					a[i] = (short)( ((double)a[i])/((double)(2*i)) );	///< Flatten function towards high freq.
				if(a[i] == 0)
					existingZeros++;
			}//end for i...
			/// Number of zeros in the test block 0...16 or 0...4.
			int numOfZeros = k % (totNumCoeffs + 1);
			/// Random unique positions for these zeros.
			if(numOfZeros > existingZeros)
			{
				for(i = 0; i < (numOfZeros - existingZeros); i++)
				{
					int attempts	= 1;
					int zeroPos		= (int)( (((double)rand()/(double)RAND_MAX) * ((double)(totNumCoeffs-1))) + 0.5 );
					while((a[zeroPos] == 0)&&(attempts < 1024))
					{
						zeroPos	= (int)( (((double)rand()/(double)RAND_MAX) * ((double)(totNumCoeffs-1))) + 0.5 );
						attempts++;
					}//end while a[]...
					a[zeroPos] = 0;
				}//end for i...
			}//end if numOfZeros...
			/// Number of trailing ones in the test block 0...3.
			int numOfOnes = k % 4;
			/// Replace non-zero coeffs from the end with ones.
			for(i = (totNumCoeffs-1); (i >= 0)&&(numOfOnes > 0); i--)
			{
				if(a[i] != 0)
				{
					if(a[i] < 0)
						a[i] = -1;
					else
						a[i] = 1;
					numOfOnes--;
				}//end if a[]...
			}//end for i...

			/// Now do the actual test.
			for(int dcSkip = 0; dcSkip <= 1; dcSkip++)
			{
				for(nC = 0; nC <= totNumCoeffs; nC++)	///< Step through all neighbourhood coeff totals.
				{
					pCAVLC->SetParameter(CAVLCH264Impl::NUM_TOT_NEIGHBOR_COEFF_ID, nC);
					pCAVLC->SetParameter(CAVLCH264Impl::DC_SKIP_FLAG_ID, 0);

					/// Encoding.
					pBsw->Reset();
					int numEncodedBits = pCAVLC->Encode(a, pBsw);

					/// Decoding.
					pBsr->Reset();
					int numDecodedBits = pCAVLC->Decode(pBsr, b);

					for(j = pCAVLC->GetParameter(CAVLCH264Impl::DC_SKIP_FLAG_ID); j < totNumCoeffs; j++)
					{
						if(a[j] != b[j])
							result = 0;
					}//end for j...
				}//end for nC...
			}//end for dcSkip...
		}//end for k...

	}//end for mode...

	delete pCAVLC;

	delete pRunBeforeVlcDec;
	delete pRunBeforeVlcEnc;
	delete pTotalZeros2x4VlcDec;
	delete pTotalZeros2x4VlcEnc;
	delete pTotalZeros2x2VlcDec;
	delete pTotalZeros2x2VlcEnc;
	delete pTotalZeros4x4VlcDec;
	delete pTotalZeros4x4VlcEnc;
	delete pCoeffTokenVlcDec;
	delete pCoeffTokenVlcEnc;
	delete pPrefixVlcDec;
	delete pPrefixVlcEnc;

	delete pBsr;
	delete pBsw;

	return(result);
}//end TestCAVLC.

/** Test block layer encode and decode implementations.
@return	: 1 = success, 0 = failed..
*/
int H264v2Codec::TestBlockLayer(void)
{
	int i,j,test,ret;
	int result = 1;
	int TESTS = 1024;

	int q			= 1;	///< Step size.
	int	qErr	= q + (q/2) + 1;

	/// Block coding order as defined by H.264 standard.
	int macroBlkCodingOrderY[4][4] =
		{ { 0, 0, 1, 1 }, 
			{ 0, 0, 1, 1 }, 
			{ 2, 2, 3, 3 }, 
			{ 2, 2, 3, 3 } 
		};
	int macroBlkCodingOrderX[4][4] =
		{ { 0, 1, 0, 1 }, 
			{ 2, 3, 2, 3 }, 
			{ 0, 1, 0, 1 }, 
			{ 2, 3, 2, 3 } 
		};

	/// Simulate a macroblock structure with one 16x16 luminance and two 
	/// 8x8 chrominance components.
	short Yo[256], Uo[64], Vo[64];
	short Y[256], U[64], V[64];
	/// Create 4x4 mem overlays on the macroblock.
	OverlayMem2Dv2* pY = new OverlayMem2Dv2(Y, 16, 16, 4, 4);
	OverlayMem2Dv2* pU = new OverlayMem2Dv2(U, 8, 8, 4, 4);
	OverlayMem2Dv2* pV = new OverlayMem2Dv2(V, 8, 8, 4, 4);
	/// ...and now for the blocks. Included are one lum 4x4 DC block and
	/// two chr 2x2 DC blocks. Overlays are created on instantiation.
	BlockH264 Yblk[4][4]; ///< Default block dimensions are 4x4.
	BlockH264 Ublk[2][2];
	BlockH264 Vblk[2][2];

	for(i = 0; i < 4; i++)	///< Initialise all location aware members.
		for(j = 0; j < 4; j++)
		{
			/// Lum.
			Yblk[i][j]._offX	= j*4;
			Yblk[i][j]._offY	= i*4;
			if(i == 0)	///< Falls into MB above and in row 3.
				Yblk[i][j]._blkAbove = NULL;	///< In this case, there are no MBs above, so set to invalid.	
			else
				Yblk[i][j]._blkAbove = &(Yblk[i-1][j]); ///< In current MB.
			if(j == 0)	///< Falls into MB to the left and in col 3.
				Yblk[i][j]._blkLeft = NULL;	///< In this case, there are no MBs to the left, so set to invalid.
			else
				Yblk[i][j]._blkLeft = &(Yblk[i][j-1]); ///< In current MB.
			/// Chr.
			if((i < 2)&&(j < 2))
			{
				Ublk[i][j]._offX	= j*4;
				Ublk[i][j]._offY	= i*4;
				Vblk[i][j]._offX	= j*4;
				Vblk[i][j]._offY	= i*4;
				if(i == 0)	///< Falls into MB above and in row 3.
				{
					Ublk[i][j]._blkAbove = NULL;	///< In this case, there are no MBs above, so set to invalid.
					Vblk[i][j]._blkAbove = NULL;
				}//end if i...
				else
				{
					Ublk[i][j]._blkAbove = &(Ublk[i-1][j]); ///< In current MB.
					Vblk[i][j]._blkAbove = &(Vblk[i-1][j]); ///< In current MB.
				}//end else...
				if(j == 0)	///< Falls into MB to the left and in col 3.
				{
					Ublk[i][j]._blkLeft = NULL;	///< In this case, there are no MBs to the left, so set to invalid.
					Vblk[i][j]._blkLeft = NULL;
				}//end if j...
				else
				{
					Ublk[i][j]._blkLeft = &(Ublk[i][j-1]); ///< In current MB.
					Vblk[i][j]._blkLeft = &(Vblk[i][j-1]); ///< In current MB.
				}//end else...
			}//end if i...
		}//end for i & j...
	/// Ignore neighbourhood of DC blocks (for this test).
	BlockH264 YDCblk;
	BlockH264 UDCblk(2,2);
	BlockH264 VDCblk(2,2);

	/// Create Integer Transformers and their inverses to convert the test values.
	IForwardTransform* pF4x4T = new FastForward4x4ITImpl1();
	pF4x4T->SetParameter(IForwardTransform::QUANT_ID, q);
	pF4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	pF4x4T->SetMode(IForwardTransform::TransformOnly);

	IForwardTransform* pFDC4x4T = new FastForwardDC4x4ITImpl1();
	pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, q);
	pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);

	IForwardTransform* pFDC2x2T = new FastForwardDC2x2ITImpl1();
	pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, q);
	pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	pFDC2x2T->SetMode(IForwardTransform::TransformAndQuant);

	/// Create an inverse IT to use and to compare with.
	IInverseTransform* pI4x4T = new FastInverse4x4ITImpl1();
	pI4x4T->SetParameter(IInverseTransform::QUANT_ID, q);
	pI4x4T->SetMode(IInverseTransform::TransformOnly);

	IInverseTransform* pIDC4x4T = new FastInverseDC4x4ITImpl1();
	pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, q);
	pIDC4x4T->SetMode(IInverseTransform::TransformAndQuant);

	IInverseTransform* pIDC2x2T = new FastInverseDC2x2ITImpl1();
	pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, q);
	pIDC2x2T->SetMode(IInverseTransform::TransformAndQuant);

	/// Use a bit stream reader/writer to code to and from.
	int bitSize = H264V2C_BYTESIZE * 8;
	unsigned char stream[H264V2C_BYTESIZE];
	IBitStreamWriter* pBsw = new BitStreamWriterMSB();
	pBsw->SetStream((void *)stream, bitSize);
	IBitStreamReader* pBsr = new BitStreamReaderMSB();
	pBsr->SetStream((void *)stream, bitSize);

	/// Create the vlc encoders and decoders for use with CAVLC.
	IVlcEncoder*	pPrefixVlcEnc					= new PrefixH264VlcEncoderImpl1();
	IVlcDecoder*	pPrefixVlcDec					= new PrefixH264VlcDecoderImpl1();
	IVlcEncoder*	pCoeffTokenVlcEnc			= new CoeffTokenH264VlcEncoder();
	IVlcDecoder*	pCoeffTokenVlcDec			= new CoeffTokenH264VlcDecoder();
	IVlcEncoder*	pTotalZeros4x4VlcEnc	= new TotalZeros4x4H264VlcEncoder();
	IVlcDecoder*	pTotalZeros4x4VlcDec	= new TotalZeros4x4H264VlcDecoder();
	IVlcEncoder*	pTotalZeros2x2VlcEnc	= new TotalZeros2x2H264VlcEncoder();
	IVlcDecoder*	pTotalZeros2x2VlcDec	= new TotalZeros2x2H264VlcDecoder();
	IVlcEncoder*	pRunBeforeVlcEnc			= new RunBeforeH264VlcEncoder();
	IVlcDecoder*	pRunBeforeVlcDec			= new RunBeforeH264VlcDecoder();

	/// Create a CAVLC for each type.
	IContextAwareRunLevelCodec* pCAVLC4x4 = new CAVLCH264Impl();
	IContextAwareRunLevelCodec* pCAVLC2x2 = new CAVLCH264Impl();
	/// Attach the vlc encoders and decoders excluding the total zeros vlc.
	pCAVLC4x4->SetMode(CAVLCH264Impl::Mode4x4);
	((CAVLCH264Impl *)pCAVLC4x4)->SetTokenCoeffVlcEncoder(pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)pCAVLC4x4)->SetTokenCoeffVlcDecoder(pCoeffTokenVlcDec);
	((CAVLCH264Impl *)pCAVLC4x4)->SetPrefixVlcEncoder(pPrefixVlcEnc);
	((CAVLCH264Impl *)pCAVLC4x4)->SetPrefixVlcDecoder(pPrefixVlcDec);
	((CAVLCH264Impl *)pCAVLC4x4)->SetRunBeforeVlcEncoder(pRunBeforeVlcEnc);
	((CAVLCH264Impl *)pCAVLC4x4)->SetRunBeforeVlcDecoder(pRunBeforeVlcDec);
	((CAVLCH264Impl *)pCAVLC4x4)->SetTotalZerosVlcEncoder(pTotalZeros4x4VlcEnc);
	((CAVLCH264Impl *)pCAVLC4x4)->SetTotalZerosVlcDecoder(pTotalZeros4x4VlcDec);

	pCAVLC2x2->SetMode(CAVLCH264Impl::Mode2x2);
	((CAVLCH264Impl *)pCAVLC2x2)->SetTokenCoeffVlcEncoder(pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)pCAVLC2x2)->SetTokenCoeffVlcDecoder(pCoeffTokenVlcDec);
	((CAVLCH264Impl *)pCAVLC2x2)->SetPrefixVlcEncoder(pPrefixVlcEnc);
	((CAVLCH264Impl *)pCAVLC2x2)->SetPrefixVlcDecoder(pPrefixVlcDec);
	((CAVLCH264Impl *)pCAVLC2x2)->SetRunBeforeVlcEncoder(pRunBeforeVlcEnc);
	((CAVLCH264Impl *)pCAVLC2x2)->SetRunBeforeVlcDecoder(pRunBeforeVlcDec);
	((CAVLCH264Impl *)pCAVLC2x2)->SetTotalZerosVlcEncoder(pTotalZeros2x2VlcEnc);
	((CAVLCH264Impl *)pCAVLC2x2)->SetTotalZerosVlcDecoder(pTotalZeros2x2VlcDec);

	/// Simulate a macroblock of YUV values at a mid point and then random
	/// deviations from it with a limited range for each test.
	srand(23995);
	for(test = 0; test < TESTS; test++)
	{
		/// **** Construct a typical test sample macroblock. Midpoint between -256..255.
		short midPoint = (short)( (((double)rand()/(double)RAND_MAX) * 511.0) - 256.0 + 0.5 );
		/// Deviation limit between 0..128.
		short devLimit = (short)( (((double)rand()/(double)RAND_MAX) * 128.0) + 0.5 );
		for(i = 0; i < 256; i++)	///< Lum and Chr.
		{
			int x = (short)( (((double)rand()/(double)RAND_MAX) * (double)devLimit) - ((double)devLimit/2.0) + 0.5 );
			x = x + midPoint;
			if(x > 255) x = 255;
			else if(x < -255) x = -255;
			Yo[i] = x;
			Y[i]	= Yo[i];
			if(i < 64)	///< Chr sample.
			{
				/// Range is halved for Chr.
				x = (short)( (((double)rand()/(double)RAND_MAX) * ((double)devLimit/2.0)) - ((double)devLimit/4.0) + 0.5 );
				x = x + midPoint;
				if(x > 255) x = 255;
				else if(x < -255) x = -255;
				Uo[i] = x;
				U[i]	= Uo[i];
				x = (short)( (((double)rand()/(double)RAND_MAX) * ((double)devLimit/2.0)) - ((double)devLimit/4.0) + 0.5 );
				x = x + midPoint;
				if(x > 255) x = 255;
				else if(x < -255) x = -255;
				Vo[i] = x;
				V[i]	= Vo[i];
			}//end if Chr...
		}//end for i...

		/// ************ Encode **************

		/// Load each block from the macroblock and apply the forward transform.
		for(i = 0; i < 4; i++)	///< 16 Lum blocks + 4 U Chr and 4 V Chr blocks.
			for(j = 0; j < 4; j++)
			{
				/// Lum.
				pY->SetOrigin(Yblk[i][j]._offX, Yblk[i][j]._offY);	///< Set overlay origin for macroblock.
				/// Copy from macroblock to block.
				pY->Read(*(Yblk[i][j].GetBlkOverlay()));
				/// Transform without scaling and quant.
				Yblk[i][j].ForwardTransform(pF4x4T);

				/// Chr.
				if((i < 2)&&(j < 2))
				{
					pU->SetOrigin(Ublk[i][j]._offX, Ublk[i][j]._offY);
					/// Copy from macroblock to block.
					pU->Read(*(Ublk[i][j].GetBlkOverlay()));
					/// Transform.
					Ublk[i][j].ForwardTransform(pF4x4T);

					pV->SetOrigin(Vblk[i][j]._offX, Vblk[i][j]._offY);
					/// Copy from macroblock to block.
					pV->Read(*(Vblk[i][j].GetBlkOverlay()));
					/// Transform.
					Vblk[i][j].ForwardTransform(pF4x4T);
				}//end if i...

			}//end for i & j...

		/// Pull out the Lum DC components. This is done in the 16x16 Intra mode only.
		short* pYDC = YDCblk.GetBlk();
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				pYDC[4*i + j] = Yblk[i][j].GetDC();
				Yblk[i][j].SetDC(0);	///< Not really necessary.
			}//end for i & j...
		/// Transform & quantise Lum DC components.
		YDCblk.ForwardTransform(pFDC4x4T);

		/// Pull out the Chr DC components. This is done in all modes.
		short* pUDC = UDCblk.GetBlk();
		short* pVDC = VDCblk.GetBlk();
		for(i = 0; i < 2; i++)
			for(j = 0; j < 2; j++)
			{
				pUDC[2*i + j] = Ublk[i][j].GetDC();
				Ublk[i][j].SetDC(0);
				pVDC[2*i + j] = Vblk[i][j].GetDC();
				Vblk[i][j].SetDC(0);
			}//end for i & j...
		/// Transform & quantise Chr DC components.
		UDCblk.ForwardTransform(pFDC2x2T);
		VDCblk.ForwardTransform(pFDC2x2T);

		/// Quantise the main blocks.
		for(i = 0; i < 4; i++)	///< 16 Lum blocks + 4 U Chr and 4 V Chr blocks.
			for(j = 0; j < 4; j++)
			{
				/// Lum.
				Yblk[i][j].Quantise(pF4x4T, q);
				/// Chr.
				if((i < 2)&&(j < 2))
				{
					Ublk[i][j].Quantise(pF4x4T, q);
					Vblk[i][j].Quantise(pF4x4T, q);
				}//end if i...
			}//end for i & j...

		/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
		/// to the required H.264 coding order of each block.
		pBsw->Reset();
		int numLumNeighborCoeffs	= 0;
		int numUChrNeighborCoeffs = 0;
		int numVChrNeighborCoeffs = 0;
		/// Lum DC first. Block num = -1.
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 0);											///< Include DC for DC Lum block.
		pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, 0);						///< This would be found from neighboring MBs.
		ret = pCAVLC4x4->Encode(YDCblk.GetBlk(), pBsw);															///< Put onto coded stream.
		if(ret <= 0)	///< Codec errors are detected from a negative return value.
			result = 0;
		YDCblk.SetNumCoeffs(pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		///< 16 Lum blocks without DC value. Block num = 0..15
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 4; i++)	
			for(j = 0; j < 4; j++)	
			{
				int blkY = macroBlkCodingOrderY[i][j];
				int blkX = macroBlkCodingOrderX[i][j];
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Yblk[blkY][blkX]._blkAbove != NULL)
					neighCoeffs += (Yblk[blkY][blkX]._blkAbove)->GetNumCoeffs();
				if(Yblk[blkY][blkX]._blkLeft != NULL)
					neighCoeffs += (Yblk[blkY][blkX]._blkLeft)->GetNumCoeffs();
				if((Yblk[blkY][blkX]._blkAbove != NULL)&&(Yblk[blkY][blkX]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Put onto coded stream.
				ret = pCAVLC4x4->Encode(Yblk[blkY][blkX].GetBlk(), pBsw);										
				int numCoeffs = pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID);
				Yblk[blkY][blkX].SetNumCoeffs(numCoeffs);															///< Set this block's coeff num for later use.
				if(numCoeffs > 0)																											///< Set the coded/no coded flag
					Yblk[blkY][blkX].SetCoded(1);
				else
					Yblk[blkY][blkX].SetCoded(0);
			}//end for i & j...
		/// Chr DC next. Block num = 16 & 17.
		pCAVLC2x2->SetParameter(pCAVLC2x2->DC_SKIP_FLAG_ID, 0);											///< Include DC for DC Chr blocks.
		pCAVLC2x2->SetParameter(pCAVLC2x2->NUM_TOT_NEIGHBOR_COEFF_ID, -1);					///< Fixed at -1 for chroma_format_idc = 1.
		ret = pCAVLC2x2->Encode(UDCblk.GetBlk(), pBsw);															///< Put Chr U onto coded stream.
		UDCblk.SetNumCoeffs(pCAVLC2x2->GetParameter(pCAVLC2x2->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		ret = pCAVLC2x2->Encode(VDCblk.GetBlk(), pBsw);															///< Put Chr V onto coded stream.
		VDCblk.SetNumCoeffs(pCAVLC2x2->GetParameter(pCAVLC2x2->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		///< 4 U Chr blocks without DC value. Block num = 18..21
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 2; i++)	
			for(j = 0; j < 2; j++)	
			{
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Ublk[i][j]._blkAbove != NULL)
					neighCoeffs += (Ublk[i][j]._blkAbove)->GetNumCoeffs();
				if(Ublk[i][j]._blkLeft != NULL)
					neighCoeffs += (Ublk[i][j]._blkLeft)->GetNumCoeffs();
				if((Ublk[i][j]._blkAbove != NULL)&&(Ublk[i][j]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Put onto coded stream.
				ret = pCAVLC4x4->Encode(Ublk[i][j].GetBlk(), pBsw);																		
				int numCoeffs = pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID);
				Ublk[i][j].SetNumCoeffs(numCoeffs);															///< Set this block's coeff num for later use.
				if(numCoeffs > 0)																								///< Set the coded/no coded flag
					Ublk[i][j].SetCoded(1);
				else
					Ublk[i][j].SetCoded(0);
			}//end for i & j...
		///< 4 V Chr blocks without DC value. Block num = 22..25
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 2; i++)	
			for(j = 0; j < 2; j++)	
			{
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Vblk[i][j]._blkAbove != NULL)
					neighCoeffs += (Vblk[i][j]._blkAbove)->GetNumCoeffs();
				if(Ublk[i][j]._blkLeft != NULL)
					neighCoeffs += (Vblk[i][j]._blkLeft)->GetNumCoeffs();
				if((Vblk[i][j]._blkAbove != NULL)&&(Vblk[i][j]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Put onto coded stream.
				ret = pCAVLC4x4->Encode(Vblk[i][j].GetBlk(), pBsw);
				int numCoeffs = pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID);
				Vblk[i][j].SetNumCoeffs(numCoeffs);															///< Set this block's coeff num for later use.
				if(numCoeffs > 0)																								///< Set the coded/no coded flag.
					Vblk[i][j].SetCoded(1);
				else
					Vblk[i][j].SetCoded(0);
			}//end for i & j...

		/// *********** Clear all ***********
		for(i = 0; i < 256; i++)
		{
			Y[i] = 0;
			if(i < 64)
			{
				U[i] = 0;
				V[i] = 0;
			}//end if i...
		}//end for i...

		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				Yblk[i][j].Zero();
				if((i < 2)&&(j < 2))
				{
					Ublk[i][j].Zero();
					Vblk[i][j].Zero();
				}//end if i...
			}//end for i & j...
		YDCblk.Zero();
		UDCblk.Zero();
		VDCblk.Zero();

		/// *********** Decode ***********

		/// Decode the vlc blocks with the context of the neighborhood number of coeffs.
		pBsr->Reset();
		numLumNeighborCoeffs	= 0;
		numUChrNeighborCoeffs = 0;
		numVChrNeighborCoeffs = 0;
		/// Lum DC first. Block num = -1.
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 0);											///< Include DC for DC Lum block.
		pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, 0);						///< This would be found from neighboring MBs.
		ret = pCAVLC4x4->Decode(pBsr, YDCblk.GetBlk());															///< Get from coded stream.
		YDCblk.SetNumCoeffs(pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		///< 16 Lum blocks without DC value. Block num = 0..15
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 4; i++)	
			for(j = 0; j < 4; j++)	
			{
				int blkY = macroBlkCodingOrderY[i][j];
				int blkX = macroBlkCodingOrderX[i][j];
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Yblk[blkY][blkX]._blkAbove != NULL)
					neighCoeffs += (Yblk[blkY][blkX]._blkAbove)->GetNumCoeffs();
				if(Yblk[blkY][blkX]._blkLeft != NULL)
					neighCoeffs += (Yblk[blkY][blkX]._blkLeft)->GetNumCoeffs();
				if((Yblk[blkY][blkX]._blkAbove != NULL)&&(Yblk[blkY][blkX]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Get from coded stream.
				ret = pCAVLC4x4->Decode(pBsr, Yblk[blkY][blkX].GetBlk());										
				Yblk[blkY][blkX].SetNumCoeffs(pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID));	///< Set this block's coeff num for later use.
			}//end for i & j...
		/// Chr DC next. Block num = 16 & 17.
		pCAVLC2x2->SetParameter(pCAVLC2x2->DC_SKIP_FLAG_ID, 0);											///< Include DC for DC Chr blocks.
		pCAVLC2x2->SetParameter(pCAVLC2x2->NUM_TOT_NEIGHBOR_COEFF_ID, -1);					///< Fixed at -1 for chroma_format_idc = 1.
		ret = pCAVLC2x2->Decode(pBsr, UDCblk.GetBlk());															///< Get Chr U from coded stream.
		UDCblk.SetNumCoeffs(pCAVLC2x2->GetParameter(pCAVLC2x2->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		ret = pCAVLC2x2->Decode(pBsr, VDCblk.GetBlk());															///< Get Chr V from coded stream.
		VDCblk.SetNumCoeffs(pCAVLC2x2->GetParameter(pCAVLC2x2->NUM_TOT_COEFF_ID));	///< Set this block's coeff num. (Not used here.)
		///< 4 U Chr blocks without DC value. Block num = 18..21
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 2; i++)	
			for(j = 0; j < 2; j++)	
			{
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Ublk[i][j]._blkAbove != NULL)
					neighCoeffs += (Ublk[i][j]._blkAbove)->GetNumCoeffs();
				if(Ublk[i][j]._blkLeft != NULL)
					neighCoeffs += (Ublk[i][j]._blkLeft)->GetNumCoeffs();
				if((Ublk[i][j]._blkAbove != NULL)&&(Ublk[i][j]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Get from coded stream.
				ret = pCAVLC4x4->Decode(pBsr, Ublk[i][j].GetBlk());
				Ublk[i][j].SetNumCoeffs(pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID));	///< Set this block's coeff num for later use.
			}//end for i & j...
		///< 4 V Chr blocks without DC value. Block num = 22..25
		pCAVLC4x4->SetParameter(pCAVLC4x4->DC_SKIP_FLAG_ID, 1);
		for(i = 0; i < 2; i++)	
			for(j = 0; j < 2; j++)	
			{
				/// Get num of neighbourhood coeffs as average of above and left block coeffs.
				int neighCoeffs = 0;
				if(Vblk[i][j]._blkAbove != NULL)
					neighCoeffs += (Vblk[i][j]._blkAbove)->GetNumCoeffs();
				if(Ublk[i][j]._blkLeft != NULL)
					neighCoeffs += (Vblk[i][j]._blkLeft)->GetNumCoeffs();
				if((Vblk[i][j]._blkAbove != NULL)&&(Vblk[i][j]._blkLeft != NULL))
					neighCoeffs = (neighCoeffs + 1)/2;
				pCAVLC4x4->SetParameter(pCAVLC4x4->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);
				/// Get from coded stream.
				ret = pCAVLC4x4->Decode(pBsr, Vblk[i][j].GetBlk());																		
				Vblk[i][j].SetNumCoeffs(pCAVLC4x4->GetParameter(pCAVLC4x4->NUM_TOT_COEFF_ID));	///< Set this block's coeff num.
			}//end for i & j...

		/// Inverse transform & inverse quantise Lum DC components.
		YDCblk.InverseTransform(pIDC4x4T);
		/// Inverse transform & inverse quantise Chr DC components.
		UDCblk.InverseTransform(pIDC2x2T);
		VDCblk.InverseTransform(pIDC2x2T);

		/// Inverse quantise the main blocks.
		for(i = 0; i < 4; i++)	///< 16 Lum blocks + 4 U Chr and 4 V Chr blocks.
			for(j = 0; j < 4; j++)
			{
				/// Lum.
				Yblk[i][j].InverseQuantise(pI4x4T, q);
				/// Chr.
				if((i < 2)&&(j < 2))
				{
					Ublk[i][j].InverseQuantise(pI4x4T, q);
					Vblk[i][j].InverseQuantise(pI4x4T, q);
				}//end if i...
			}//end for i & j...

		/// Put the Lum DC components in position with a 4x scale factor.
		pYDC = YDCblk.GetBlk();
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
				Yblk[i][j].SetDC(4 * pYDC[4*i + j]);
		/// Put the Chr DC components in position.
		pUDC = UDCblk.GetBlk();
		pVDC = VDCblk.GetBlk();
		for(i = 0; i < 2; i++)
			for(j = 0; j < 2; j++)
			{
				Ublk[i][j].SetDC(4 * pUDC[2*i + j]);
				Vblk[i][j].SetDC(4 * pVDC[2*i + j]);
			}//end for i & j...

		for(i = 0; i < 4; i++)	///< 16 Lum blocks + 4 U Chr and 4 V Chr blocks.
			for(j = 0; j < 4; j++)
			{
				/// Inverse transform.
				Yblk[i][j].InverseTransform(pI4x4T);
				/// Lum.
				pY->SetOrigin(Yblk[i][j]._offX, Yblk[i][j]._offY);	///< Set overlay origin for macroblock.
				/// Copy from block to macroblock.
				pY->Write(*(Yblk[i][j].GetBlkOverlay()));

				/// Chr.
				if((i < 2)&&(j < 2))
				{
					/// Inverse transform.
					Ublk[i][j].InverseTransform(pI4x4T);
					pU->SetOrigin(Ublk[i][j]._offX, Ublk[i][j]._offY);
					/// Copy from block to macroblock.
					pU->Write(*(Ublk[i][j].GetBlkOverlay()));

					/// Inverse transform.
					Vblk[i][j].InverseTransform(pI4x4T);
					pV->SetOrigin(Vblk[i][j]._offX, Vblk[i][j]._offY);
					/// Copy from block to macroblock.
					pV->Write(*(Vblk[i][j].GetBlkOverlay()));
				}//end if i...

			}//end for i & j...

		/// ************ Evaluate ******************
		for(i = 0; i < 256; i++)
		{
			if( abs(Y[i] - Yo[i]) > qErr )	///< Allow rounding error.
				result = 0;
			if(i < 64)
			{
				if( abs(U[i] - Uo[i]) > qErr )
					result = 0;
				if( abs(V[i] - Vo[i]) > qErr )
					result = 0;
			}//end if i...
		}//end for i...

	}//end for test...

	/// Chuck out everything in reverse order of instantiation.
	delete pCAVLC2x2;
	delete pCAVLC4x4;
	delete pPrefixVlcEnc;
	delete pPrefixVlcDec;
	delete pCoeffTokenVlcEnc;
	delete pCoeffTokenVlcDec;
	delete pTotalZeros4x4VlcEnc;
	delete pTotalZeros4x4VlcDec;
	delete pTotalZeros2x2VlcEnc;
	delete pTotalZeros2x2VlcDec;
	delete pRunBeforeVlcEnc;
	delete pRunBeforeVlcDec;
	delete pBsw;
	delete pBsr;
	delete pIDC2x2T;
	delete pIDC4x4T;
	delete pI4x4T;
	delete pFDC2x2T;
	delete pFDC4x4T;
	delete pF4x4T;
	delete pV;
	delete pU;
	delete pY;

	return(result);
}//end TestBlockLayer.

========== END FILE: CodecUtils/CodeFragmentForH264BlockLayerTest.cpp ==========

========== BEGIN FILE: CodecUtils/CoeffTokenH264VlcDecoder.cpp ==========
Bundle entry: 22
Original bytes: 40946
Original SHA-256: 00aa6afab0cafc3677866073a186da90fab39876045327c15e4f060f0d1dccb7
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CoeffTokenH264VlcDecoder

TAG						: CTH264VD

FILE NAME			: CoeffTokenH264VlcDecoder.cpp

DESCRIPTION		: A coeff token Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.2 page 200. The 
								trailing ones and total coeffs are combined in this token 
								and is dependent on the neighbouring blocks' total number
								of coeffs. This implementation is implemented with an
								IVlcDecoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "CoeffTokenH264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
CoeffTokenH264VlcDecoder::CoeffTokenH264VlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

CoeffTokenH264VlcDecoder::~CoeffTokenH264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode total coeff - trailing ones - neighbour total coeffs symbols from the bit stream.
The first 2 param symbols represent total coeffs and trailing ones are decoded from the stream. The 
3rd symbol is the neighbourhood total coeffs that is an input to this method and is used to select
the appropriate codeword table. For fast implementation the tree splitting is done in the code.
@param bsr			: Bit stream to get from.
@param symbol1	: Returned total coeffs for this block
@param symbol2	: Returned num of trailing ones for this block
@param symbol3	: Total num of coeffs in neighbourhood blocks
@return					: Num of bits extracted.
*/
int	CoeffTokenH264VlcDecoder::Decode3(IBitStreamReader* bsr, int* symbol1, int* symbol2, int* symbol3)
{
	int numTotNeighborCoeff	= *symbol3;	///< Used as an input.

	/// Reset bits extracted.
  _numCodeBits = 0;

	/// Select the table depending on the neighbourhood total number of coeffs.
	switch(numTotNeighborCoeff)
	{
		case 0:
		case 1:
			_numCodeBits	= NC0to1(bsr, symbol1, symbol2);
			break;
		case 2:
		case 3:
			_numCodeBits	= NC2to3(bsr, symbol1, symbol2);
			break;
		case 4:
		case 5:
		case 6:
		case 7:
			_numCodeBits	= NC4to7(bsr, symbol1, symbol2);
			break;
		case -1:
			_numCodeBits	= NCneg1(bsr, symbol1, symbol2);
			break;
		case -2:
			_numCodeBits	= NCneg2(bsr, symbol1, symbol2);
			break;
		default:	///< Greater than or equal to 8.
			_numCodeBits	= NC8up(bsr, symbol1, symbol2);
			break;
	}//end switch numTotNeighborCoeff...

  return(_numCodeBits);
}//end Decode3.

/*
---------------------------------------------------------------------------
	Private Methods.
---------------------------------------------------------------------------
*/
/** Decode total coeff - trailing ones symbols from the bit stream.
For neighbourhood total coeffs from 0 to 1, 2 to 3, 4 to 7, above 8, -1
and -2.
@param bsr					: Bit stream to get from.
@param totalCoeffs	: Returned total coeffs for this block
@param trailingOnes	: Returned num of trailing ones for this block
@return							: Num of bits extracted.
*/
int	CoeffTokenH264VlcDecoder::NC0to1(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	int numBits	= 0;
	int tCs			= 0;
	int tOs			= 0;
	int bits;

	/// Work through the bits from the stream one at a time or in groups if appropriate.
	if(bsr->Read())	///< 1
	{
		numBits	= 1; tOs = 0; tCs = 0;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			numBits	= 2; tOs = 1; tCs = 1;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits	= 3; tOs = 2; tCs = 2;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						numBits	= 5; tOs = 3; tCs = 3;
					}//end if 0001 1...
					else						///< 0001 0
					{
						if(bsr->Read())	///< 0001 01
						{
							numBits	= 6; tOs = 0; tCs = 1;
						}//end if 0001 01...
						else						///< 0001 00
						{
							numBits	= 6; tOs = 1; tCs = 2;
						}//end else 0001 00...
					}//end else 0001 0...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						if(bsr->Read())	///< 0000 11
						{
							numBits	= 6; tOs = 3; tCs = 4;
						}//end if 0000 11...
						else						///< 0000 10
						{
							if(bsr->Read())	///< 0000 101
							{
								numBits	= 7; tOs = 2; tCs = 3;
							}//end if 0000 101...
							else						///< 0000 100
							{
								numBits	= 7; tOs = 3; tCs = 5;
							}//end else 0000 100...
						}//end else 0000 10...
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							bits = bsr->Read(2);
							switch(bits)
							{
								case 0:			///< 0000 0100
									numBits	= 8; tOs = 3; tCs = 6;
									break;
								case 1:			///< 0000 0101
									numBits	= 8; tOs = 2; tCs = 4;
									break;
								case 2:			///< 0000 0110
									numBits	= 8; tOs = 1; tCs = 3;
									break;
								case 3:			///< 0000 0111
									numBits	= 8; tOs = 0; tCs = 2;
									break;
							}//end switch bits...
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								bits = bsr->Read(2);
								switch(bits)
								{
									case 0:			///< 0000 0010 0
										numBits	= 9; tOs = 3; tCs = 7;
										break;
									case 1:			///< 0000 0010 1
										numBits	= 9; tOs = 2; tCs = 5;
										break;
									case 2:			///< 0000 0011 0
										numBits	= 9; tOs = 1; tCs = 4;
										break;
									case 3:			///< 0000 0011 1
										numBits	= 9; tOs = 0; tCs = 3;
										break;
								}//end switch bits...
							}//end if 0000 001...
							else						///< 0000 000
							{
								if(bsr->Read())	///< 0000 0001
								{
									bits = bsr->Read(2);
									switch(bits)
									{
										case 0:			///< 0000 0001 00
											numBits	= 10; tOs = 3; tCs = 8;
											break;
										case 1:			///< 0000 0001 01
											numBits	= 10; tOs = 2; tCs = 6;
											break;
										case 2:			///< 0000 0001 10
											numBits	= 10; tOs = 1; tCs = 5;
											break;
										case 3:			///< 0000 0001 11
											numBits	= 10; tOs = 0; tCs = 4;
											break;
									}//end switch bits...
								}//end if 0000 0001...
								else						///< 0000 0000
								{
									if(bsr->Read())	///< 0000 0000 1
									{
										bits = bsr->Read(2);
										switch(bits)
										{
											case 0:			///< 0000 0000 100
												numBits	= 11; tOs = 3; tCs = 9;
												break;
											case 1:			///< 0000 0000 101
												numBits	= 11; tOs = 2; tCs = 7;
												break;
											case 2:			///< 0000 0000 110
												numBits	= 11; tOs = 1; tCs = 6;
												break;
											case 3:			///< 0000 0000 111
												numBits	= 11; tOs = 0; tCs = 5;
												break;
										}//end switch bits...
									}//end if 0000 0000 1...
									else						///< 0000 0000 0
									{
										if(bsr->Read())	///< 0000 0000 01
										{
											bits = bsr->Read(3);
											switch(bits)
											{
												case 0:			///< 0000 0000 0100 0
													numBits	= 13; tOs = 0; tCs = 8;
													break;
												case 1:			///< 0000 0000 0100 1
													numBits	= 13; tOs = 2; tCs = 9;
													break;
												case 2:			///< 0000 0000 0101 0
													numBits	= 13; tOs = 1; tCs = 8;
													break;
												case 3:			///< 0000 0000 0101 1
													numBits	= 13; tOs = 0; tCs = 7;
													break;
												case 4:			///< 0000 0000 0110 0
													numBits	= 13; tOs = 3; tCs = 10;
													break;
												case 5:			///< 0000 0000 0110 1
													numBits	= 13; tOs = 2; tCs = 8;
													break;
												case 6:			///< 0000 0000 0111 0
													numBits	= 13; tOs = 1; tCs = 7;
													break;
												case 7:			///< 0000 0000 0111 1
													numBits	= 13; tOs = 0; tCs = 6;
													break;
											}//end switch bits...
										}//end if 0000 0000 01...
										else						///< 0000 0000 00
										{
											if(bsr->Read())	///< 0000 0000 001
											{
												bits = bsr->Read(3);
												switch(bits)
												{
													case 0:			///< 0000 0000 0010 00
														numBits	= 14; tOs = 3; tCs = 12;
														break;
													case 1:			///< 0000 0000 0010 01
														numBits	= 14; tOs = 2; tCs = 11;
														break;
													case 2:			///< 0000 0000 0010 10
														numBits	= 14; tOs = 1; tCs = 10;
														break;
													case 3:			///< 0000 0000 0010 11
														numBits	= 14; tOs = 0; tCs = 10;
														break;
													case 4:			///< 0000 0000 0011 00
														numBits	= 14; tOs = 3; tCs = 11;
														break;
													case 5:			///< 0000 0000 0011 01
														numBits	= 14; tOs = 2; tCs = 10;
														break;
													case 6:			///< 0000 0000 0011 10
														numBits	= 14; tOs = 1; tCs = 9;
														break;
													case 7:			///< 0000 0000 0011 11
														numBits	= 14; tOs = 0; tCs = 9;
														break;
												}//end switch bits...
											}//end if 0000 0000 001...
											else						///< 0000 0000 000
											{
												if(bsr->Read())	///< 0000 0000 0001
												{
													bits = bsr->Read(3);
													switch(bits)
													{
														case 0:			///< 0000 0000 0001 000
															numBits	= 15; tOs = 3; tCs = 14;
															break;
														case 1:			///< 0000 0000 0001 001
															numBits	= 15; tOs = 2; tCs = 13;
															break;
														case 2:			///< 0000 0000 0001 010
															numBits	= 15; tOs = 1; tCs = 12;
															break;
														case 3:			///< 0000 0000 0001 011
															numBits	= 15; tOs = 0; tCs = 12;
															break;
														case 4:			///< 0000 0000 0001 100
															numBits	= 15; tOs = 3; tCs = 13;
															break;
														case 5:			///< 0000 0000 0001 101
															numBits	= 15; tOs = 2; tCs = 12;
															break;
														case 6:			///< 0000 0000 0001 110
															numBits	= 15; tOs = 1; tCs = 11;
															break;
														case 7:			///< 0000 0000 0001 111
															numBits	= 15; tOs = 0; tCs = 11;
															break;
													}//end switch bits...
												}//end if 0000 0000 0001...
												else						///< 0000 0000 0000
												{
													if(bsr->Read())	///< 0000 0000 0000 1
													{
														bits = bsr->Read(3);
														switch(bits)
														{
															case 0:			///< 0000 0000 0000 1000
																numBits	= 16; tOs = 3; tCs = 16;
																break;
															case 1:			///< 0000 0000 0000 1001
																numBits	= 16; tOs = 2; tCs = 15;
																break;
															case 2:			///< 0000 0000 0000 1010
																numBits	= 16; tOs = 1; tCs = 15;
																break;
															case 3:			///< 0000 0000 0000 1011
																numBits	= 16; tOs = 0; tCs = 14;
																break;
															case 4:			///< 0000 0000 0000 1100
																numBits	= 16; tOs = 3; tCs = 15;
																break;
															case 5:			///< 0000 0000 0000 1101
																numBits	= 16; tOs = 2; tCs = 14;
																break;
															case 6:			///< 0000 0000 0000 1110
																numBits	= 16; tOs = 1; tCs = 14;
																break;
															case 7:			///< 0000 0000 0000 1111
																numBits	= 16; tOs = 0; tCs = 13;
																break;
														}//end switch bits...
													}//end if 0000 0000 0000 1...
													else						///< 0000 0000 0000 0
													{
														if(bsr->Read())	///< 0000 0000 0000 01
														{
															bits = bsr->Read(2);
															switch(bits)
															{
																case 0:			///< 0000 0000 0000 0100
																	numBits	= 16; tOs = 0; tCs = 16;
																	break;
																case 1:			///< 0000 0000 0000 0101
																	numBits	= 16; tOs = 2; tCs = 16;
																	break;
																case 2:			///< 0000 0000 0000 0110
																	numBits	= 16; tOs = 1; tCs = 16;
																	break;
																case 3:			///< 0000 0000 0000 0111
																	numBits	= 16; tOs = 0; tCs = 15;
																	break;
															}//end switch bits...
														}//end if 0000 0000 0000 01...
														else						///< 0000 0000 0000 00
														{
															if(bsr->Read())	///< 0000 0000 0000 001
															{
																numBits	= 15; tOs = 1; tCs = 13;
															}//end if 0000 0000 0000 001...
														}//end else 0000 0000 0000 00...
													}//end else 0000 0000 0000 0...
												}//end else 0000 0000 0000...
											}//end else 0000 0000 000...
										}//end else 0000 0000 00...
									}//end else 0000 0000 0...
								}//end else 0000 0000...
							}//end else 0000 000...
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(numBits);
}//end NC0to1.

int	CoeffTokenH264VlcDecoder::NC2to3(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	int numBits	= 0;
	int tCs			= 0;
	int tOs			= 0;
	int bits;

	/// Work through the bits from the stream one at a time or in groups if appropriate.
	if(bsr->Read())	///< 1
	{
		if(bsr->Read())	///< 11
		{
			numBits	= 2; tOs = 0; tCs = 0;
		}//end if 11...
		else						///< 10
		{
			numBits	= 2; tOs = 1; tCs = 1;
		}//end else 10...
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits	= 3; tOs = 2; tCs = 2;
			}//end if 011...
			else						///< 010
			{
				if(bsr->Read())	///< 0101
				{
					numBits	= 4; tOs = 3; tCs = 3;
				}//end if 0101...
				else						///< 0100
				{
					numBits	= 4; tOs = 3; tCs = 4;
				}//end else 0100...
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					if(bsr->Read())	///< 0011 1
					{
						numBits	= 5; tOs = 1; tCs = 2;
					}//end if 0011 1...
					else						///< 0011 0
					{
						numBits	= 5; tOs = 3; tCs = 5;
					}//end else 0011 0...
				}//end if 0011...
				else						///< 0010
				{
					bits = bsr->Read(2);
					switch(bits)
					{
						case 0:			///< 0010 00
							numBits	= 6; tOs = 3; tCs = 6;
							break;
						case 1:			///< 0010 01
							numBits	= 6; tOs = 2; tCs = 3;
							break;
						case 2:			///< 0010 10
							numBits	= 6; tOs = 1; tCs = 3;
							break;
						case 3:			///< 0010 11
							numBits	= 6; tOs = 0; tCs = 1;
							break;
					}//end switch bits...
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					bits = bsr->Read(2);
					switch(bits)
					{
						case 0:			///< 0001 00
							numBits	= 6; tOs = 3; tCs = 7;
							break;
						case 1:			///< 0001 01
							numBits	= 6; tOs = 2; tCs = 4;
							break;
						case 2:			///< 0001 10
							numBits	= 6; tOs = 1; tCs = 4;
							break;
						case 3:			///< 0001 11
							numBits	= 6; tOs = 0; tCs = 2;
							break;
					}//end switch bits...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						bits = bsr->Read(2);
						switch(bits)
						{
							case 0:			///< 0000 100
								numBits	= 7; tOs = 3; tCs = 8;
								break;
							case 1:			///< 0000 101
								numBits	= 7; tOs = 2; tCs = 5;
								break;
							case 2:			///< 0000 110
								numBits	= 7; tOs = 1; tCs = 5;
								break;
							case 3:			///< 0000 111
								numBits	= 7; tOs = 0; tCs = 3;
								break;
						}//end switch bits...
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							bits = bsr->Read(2);
							switch(bits)
							{
								case 0:			///< 0000 0100
									numBits	= 8; tOs = 0; tCs = 5;
									break;
								case 1:			///< 0000 0101
									numBits	= 8; tOs = 2; tCs = 6;
									break;
								case 2:			///< 0000 0110
									numBits	= 8; tOs = 1; tCs = 6;
									break;
								case 3:			///< 0000 0111
									numBits	= 8; tOs = 0; tCs = 4;
									break;
							}//end switch bits...
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								bits = bsr->Read(2);
								switch(bits)
								{
									case 0:			///< 0000 0010 0
										numBits	= 9; tOs = 3; tCs = 9;
										break;
									case 1:			///< 0000 0010 1
										numBits	= 9; tOs = 2; tCs = 7;
										break;
									case 2:			///< 0000 0011 0
										numBits	= 9; tOs = 1; tCs = 7;
										break;
									case 3:			///< 0000 0011 1
										numBits	= 9; tOs = 0; tCs = 6;
										break;
								}//end switch bits...
							}//end if 0000 001...
							else						///< 0000 000
							{
								if(bsr->Read())	///< 0000 0001
								{
									bits = bsr->Read(3);
									switch(bits)
									{
										case 0:			///< 0000 0001 000
											numBits	= 11; tOs = 3; tCs = 11;
											break;
										case 1:			///< 0000 0001 001
											numBits	= 11; tOs = 2; tCs = 9;
											break;
										case 2:			///< 0000 0001 010
											numBits	= 11; tOs = 1; tCs = 9;
											break;
										case 3:			///< 0000 0001 011
											numBits	= 11; tOs = 0; tCs = 8;
											break;
										case 4:			///< 0000 0001 100
											numBits	= 11; tOs = 3; tCs = 10;
											break;
										case 5:			///< 0000 0001 101
											numBits	= 11; tOs = 2; tCs = 8;
											break;
										case 6:			///< 0000 0001 110
											numBits	= 11; tOs = 1; tCs = 8;
											break;
										case 7:			///< 0000 0001 111
											numBits	= 11; tOs = 0; tCs = 7;
											break;
									}//end switch bits...
								}//end if 0000 0001...
								else						///< 0000 0000
								{
									if(bsr->Read())	///< 0000 0000 1
									{
										bits = bsr->Read(3);
										switch(bits)
										{
											case 0:			///< 0000 0000 1000
												numBits	= 12; tOs = 0; tCs = 11;
												break;
											case 1:			///< 0000 0000 1001
												numBits	= 12; tOs = 2; tCs = 11;
												break;
											case 2:			///< 0000 0000 1010
												numBits	= 12; tOs = 1; tCs = 11;
												break;
											case 3:			///< 0000 0000 1011
												numBits	= 12; tOs = 0; tCs = 10;
												break;
											case 4:			///< 0000 0000 1100
												numBits	= 12; tOs = 3; tCs = 12;
												break;
											case 5:			///< 0000 0000 1101
												numBits	= 12; tOs = 2; tCs = 10;
												break;
											case 6:			///< 0000 0000 1110
												numBits	= 12; tOs = 1; tCs = 10;
												break;
											case 7:			///< 0000 0000 1111
												numBits	= 12; tOs = 0; tCs = 9;
												break;
										}//end switch bits...
									}//end if 0000 0000 1...
									else						///< 0000 0000 0
									{
										if(bsr->Read())	///< 0000 0000 01
										{
											bits = bsr->Read(3);
											switch(bits)
											{
												case 0:			///< 0000 0000 0100 0
													numBits	= 13; tOs = 3; tCs = 14;
													break;
												case 1:			///< 0000 0000 0100 1
													numBits	= 13; tOs = 2; tCs = 13;
													break;
												case 2:			///< 0000 0000 0101 0
													numBits	= 13; tOs = 1; tCs = 13;
													break;
												case 3:			///< 0000 0000 0101 1
													numBits	= 13; tOs = 0; tCs = 13;
													break;
												case 4:			///< 0000 0000 0110 0
													numBits	= 13; tOs = 3; tCs = 13;
													break;
												case 5:			///< 0000 0000 0110 1
													numBits	= 13; tOs = 2; tCs = 12;
													break;
												case 6:			///< 0000 0000 0111 0
													numBits	= 13; tOs = 1; tCs = 12;
													break;
												case 7:			///< 0000 0000 0111 1
													numBits	= 13; tOs = 0; tCs = 12;
													break;
											}//end switch bits...
										}//end if 0000 0000 01...
										else						///< 0000 0000 00
										{
											if(bsr->Read())	///< 0000 0000 001
											{
												if(bsr->Read())	///< 0000 0000 0011
												{
													if(bsr->Read())	///< 0000 0000 0011 1
													{
														numBits	= 13; tOs = 0; tCs = 14;
													}//end if 0000 0000 0011 1...
													else						///< 0000 0000 0011 0
													{
														numBits	= 13; tOs = 2; tCs = 14;
													}//end else 0000 0000 0011 0...
												}//end if 0000 0000 0011...
												else						///< 0000 0000 0010
												{
													bits = bsr->Read(2);
													switch(bits)
													{
														case 0:			///< 0000 0000 0010 00
															numBits	= 14; tOs = 1; tCs = 15;
															break;
														case 1:			///< 0000 0000 0010 01
															numBits	= 14; tOs = 0; tCs = 15;
															break;
														case 2:			///< 0000 0000 0010 10
															numBits	= 14; tOs = 2; tCs = 15;
															break;
														case 3:			///< 0000 0000 0010 11
															numBits	= 14; tOs = 1; tCs = 14;
															break;
													}//end switch bits...
												}//end else 0000 0000 0010...
											}//end if 0000 0000 001...
											else						///< 0000 0000 000
											{
												if(bsr->Read())	///< 0000 0000 0001
												{
													bits = bsr->Read(2);
													switch(bits)
													{
														case 0:			///< 0000 0000 0001 00
															numBits	= 14; tOs = 3; tCs = 16;
															break;
														case 1:			///< 0000 0000 0001 01
															numBits	= 14; tOs = 2; tCs = 16;
															break;
														case 2:			///< 0000 0000 0001 10
															numBits	= 14; tOs = 1; tCs = 16;
															break;
														case 3:			///< 0000 0000 0001 11
															numBits	= 14; tOs = 0; tCs = 16;
															break;
													}//end switch bits...
												}//end if 0000 0000 0001...
												else						///< 0000 0000 0000
												{
													if(bsr->Read())	///< 0000 0000 0000 1
													{
														numBits	= 13; tOs = 3; tCs = 15;
													}//end if 0000 0000 0000 1...
												}//end else 0000 0000 0000...
											}//end else 0000 0000 000...
										}//end else 0000 0000 00...
									}//end else 0000 0000 0...
								}//end else 0000 0000...
							}//end else 0000 000...
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(numBits);
}//end NC2to3.

int	CoeffTokenH264VlcDecoder::NC4to7(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	int numBits	= 0;
	int tCs			= 0;
	int tOs			= 0;
	int bits;

	/// Work through the bits from the stream one at a time or in groups if appropriate.
	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(3);
		switch(bits)
		{
			case 0:			///< 1000
				tOs = 3; tCs = 7;
				break;
			case 1:			///< 1001
				tOs = 3; tCs = 6;
				break;
			case 2:			///< 1010
				tOs = 3; tCs = 5;
				break;
			case 3:			///< 1011
				tOs = 3; tCs = 4;
				break;
			case 4:			///< 1100
				tOs = 3; tCs = 3;
				break;
			case 5:			///< 1101
				tOs = 2; tCs = 2;
				break;
			case 6:			///< 1110
				tOs = 1; tCs = 1;
				break;
			case 7:			///< 1111
				tOs = 0; tCs = 0;
				break;
		}//end switch bits...
		numBits = 4;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			bits = bsr->Read(3);
			switch(bits)
			{
				case 0:			///< 0100 0
					tOs = 1; tCs = 5;
					break;
				case 1:			///< 0100 1
					tOs = 2; tCs = 5;
					break;
				case 2:			///< 0101 0
					tOs = 1; tCs = 4;
					break;
				case 3:			///< 0101 1
					tOs = 2; tCs = 4;
					break;
				case 4:			///< 0110 0
					tOs = 1; tCs = 3;
					break;
				case 5:			///< 0110 1
					tOs = 3; tCs = 8;
					break;
				case 6:			///< 0111 0
					tOs = 2; tCs = 3;
					break;
				case 7:			///< 0111 1
					tOs = 1; tCs = 2;
					break;
			}//end switch bits...
			numBits = 5;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				bits = bsr->Read(3);
				switch(bits)
				{
					case 0:			///< 0010 00
						tOs = 0; tCs = 3;
						break;
					case 1:			///< 0010 01
						tOs = 2; tCs = 7;
						break;
					case 2:			///< 0010 10
						tOs = 1; tCs = 7;
						break;
					case 3:			///< 0010 11
						tOs = 0; tCs = 2;
						break;
					case 4:			///< 0011 00
						tOs = 3; tCs = 9;
						break;
					case 5:			///< 0011 01
						tOs = 2; tCs = 6;
						break;
					case 6:			///< 0011 10
						tOs = 1; tCs = 6;
						break;
					case 7:			///< 0011 11
						tOs = 0; tCs = 1;
						break;
				}//end switch bits...
				numBits = 6;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					bits = bsr->Read(3);
					switch(bits)
					{
						case 0:			///< 0001 000
							tOs = 0; tCs = 7;
							break;
						case 1:			///< 0001 001
							tOs = 0; tCs = 6;
							break;
						case 2:			///< 0001 010
							tOs = 2; tCs = 9;
							break;
						case 3:			///< 0001 011
							tOs = 0; tCs = 5;
							break;
						case 4:			///< 0001 100
							tOs = 3; tCs = 10;
							break;
						case 5:			///< 0001 101
							tOs = 2; tCs = 8;
							break;
						case 6:			///< 0001 110
							tOs = 1; tCs = 8;
							break;
						case 7:			///< 0001 111
							tOs = 0; tCs = 4;
							break;
					}//end switch bits...
					numBits = 7;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						bits = bsr->Read(3);
						switch(bits)
						{
							case 0:			///< 0000 1000
								tOs = 3; tCs = 12;
								break;
							case 1:			///< 0000 1001
								tOs = 2; tCs = 11;
								break;
							case 2:			///< 0000 1010
								tOs = 1; tCs = 10;
								break;
							case 3:			///< 0000 1011
								tOs = 0; tCs = 9;
								break;
							case 4:			///< 0000 1100
								tOs = 3; tCs = 11;
								break;
							case 5:			///< 0000 1101
								tOs = 2; tCs = 10;
								break;
							case 6:			///< 0000 1110
								tOs = 1; tCs = 9;
								break;
							case 7:			///< 0000 1111
								tOs = 0; tCs = 8;
								break;
						}//end switch bits...
						numBits = 8;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							bits = bsr->Read(3);
							switch(bits)
							{
								case 0:			///< 0000 0100 0
									tOs = 0; tCs = 12;
									break;
								case 1:			///< 0000 0100 1
									tOs = 2; tCs = 13;
									break;
								case 2:			///< 0000 0101 0
									tOs = 1; tCs = 12;
									break;
								case 3:			///< 0000 0101 1
									tOs = 0; tCs = 11;
									break;
								case 4:			///< 0000 0110 0
									tOs = 3; tCs = 13;
									break;
								case 5:			///< 0000 0110 1
									tOs = 2; tCs = 12;
									break;
								case 6:			///< 0000 0111 0
									tOs = 1; tCs = 11;
									break;
								case 7:			///< 0000 0111 1
									tOs = 0; tCs = 10;
									break;
							}//end switch bits...
							numBits = 9;
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								if(bsr->Read())	///< 0000 0011
								{
									if(bsr->Read())	///< 0000 0011 1
									{
										numBits = 9; tOs = 1; tCs = 13;
									}//end if 0000 0011 1...
									else						///< 0000 0011 0
									{
										if(bsr->Read())	///< 0000 0011 01
										{
											numBits = 10; tOs = 0; tCs = 13;
										}//end if 0000 0011 01...
										else						///< 0000 0011 00
										{
											numBits = 10; tOs = 1; tCs = 14;
										}//end else 0000 0011 00...
									}//end else 0000 0011 0...
								}//end if 0000 0011...
								else						///< 0000 0010
								{
									bits = bsr->Read(2);
									switch(bits)
									{
										case 0:			///< 0000 0010 00
											tOs = 1; tCs = 15;
											break;
										case 1:			///< 0000 0010 01
											tOs = 0; tCs = 14;
											break;
										case 2:			///< 0000 0010 10
											tOs = 3; tCs = 14;
											break;
										case 3:			///< 0000 0010 11
											tOs = 2; tCs = 14;
											break;
									}//end switch bits...
									numBits	= 10;
								}//end else 0000 0010...
							}//end if 0000 001...
							else						///< 0000 000
							{
								if(bsr->Read())	///< 0000 0001
								{
									bits = bsr->Read(2);
									switch(bits)
									{
										case 0:			///< 0000 0001 00
											tOs = 1; tCs = 16;
											break;
										case 1:			///< 0000 0001 01
											tOs = 0; tCs = 15;
											break;
										case 2:			///< 0000 0001 10
											tOs = 3; tCs = 15;
											break;
										case 3:			///< 0000 0001 11
											tOs = 2; tCs = 15;
											break;
									}//end switch bits...
									numBits	= 10;
								}//end if 0000 0001...
								else						///< 0000 0000
								{
									if(bsr->Read())	///< 0000 0000 1
									{
										if(bsr->Read())	///< 0000 0000 11
										{
											numBits = 10; tOs = 2; tCs = 16;
										}//end if 0000 0000 11...
										else						///< 0000 0000 10
										{
											numBits = 10; tOs = 3; tCs = 16;
										}//end else 0000 0000 10...
									}//end if 0000 0000 1...
									else						///< 0000 0000 0
									{
										if(bsr->Read())	///< 0000 0000 01
										{
											numBits = 10; tOs = 0; tCs = 16;
										}//end if 0000 0000 01...
									}//end else 0000 0000 0...
								}//end else 0000 0000...
							}//end else 0000 000...
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(numBits);
}//end NC4to7.

int	CoeffTokenH264VlcDecoder::NC8up(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	/// Make use of the pattern for the majority (not all) of these codes where the 1st 4 bits
	/// equal trailing coeffs - 1 and the next 2 bits equal the trailing ones. The exception is
	/// when the 1st 4 bits equal zero and the next 2 bits equal 3.

	int tCs	= bsr->Read(4) + 1;
	int tOs	= bsr->Read(2);

	/// Check for the exception.
	if( (tCs == 1)&&(tOs == 3) )	///< Not possible.
	{
		tCs = 0; tOs = 0;
	}//end if tCs...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(6);
}//end NC8up.

int	CoeffTokenH264VlcDecoder::NCneg1(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	int numBits = 0;
	int tCs			= 0;
	int tOs			= 0;

	if(bsr->Read())	///< 1
	{
		numBits = 1; tOs = 1; tCs = 1;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			numBits = 2; tOs = 0; tCs = 0;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tOs = 2; tCs = 2;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						if(bsr->Read())	///< 0001 11
						{
							numBits = 6; tOs = 0; tCs = 1;
						}//end if 0001 11...
						else						///< 0001 10
						{
							numBits = 6; tOs = 1; tCs = 2;
						}//end else 0001 10...
					}//end if 0001 1...
					else						///< 0001 0
					{
						if(bsr->Read())	///< 0001 01
						{
							numBits = 6; tOs = 3; tCs = 3;
						}//end if 0001 01...
						else						///< 0001 00
						{
							numBits = 6; tOs = 0; tCs = 2;
						}//end else 0001 00...
					}//end else 0001 0...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						if(bsr->Read())	///< 0000 11
						{
							numBits = 6; tOs = 0; tCs = 3;
						}//end if 0000 11...
						else						///< 0000 10
						{
							numBits = 6; tOs = 0; tCs = 4;
						}//end else 0000 10...
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							if(bsr->Read())	///< 0000 011
							{
								numBits = 7; tOs = 1; tCs = 3;
							}//end if 0000 011...
							else						///< 0000 010
							{
								numBits = 7; tOs = 2; tCs = 3;
							}//end else 0000 010...
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								if(bsr->Read())	///< 0000 0011
								{
									numBits = 8; tOs = 1; tCs = 4;
								}//end if 0000 0011...
								else						///< 0000 0010
								{
									numBits = 8; tOs = 2; tCs = 4;
								}//end else 0000 0010...
							}//end if 0000 001...
							else						///< 0000 000
							{
								numBits = 7; tOs = 3; tCs = 4;
							}//end else 0000 000...
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(numBits);
}//end NCneg1.

int	CoeffTokenH264VlcDecoder::NCneg2(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes)
{
	int numBits = 0;
	int tCs			= 0;
	int tOs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		numBits = 1; tOs = 0; tCs = 0;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			numBits = 2; tOs = 1; tCs = 1;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tOs = 2; tCs = 2;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					bits = bsr->Read(3);
					switch(bits)
					{
						case 0:			///< 0001 000
							tOs = 3; tCs = 6;
							break;
						case 1:			///< 0001 001
							tOs = 3; tCs = 5;
							break;
						case 2:			///< 0001 010
							tOs = 2; tCs = 4;
							break;
						case 3:			///< 0001 011
							tOs = 2; tCs = 3;
							break;
						case 4:			///< 0001 100
							tOs = 1; tCs = 3;
							break;
						case 5:			///< 0001 101
							tOs = 1; tCs = 2;
							break;
						case 6:			///< 0001 110
							tOs = 0; tCs = 2;
							break;
						case 7:			///< 0001 111
							tOs = 0; tCs = 1;
							break;
					}//end switch bits...
					numBits = 7;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tOs = 3; tCs = 3;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tOs = 3; tCs = 4;
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								bits = bsr->Read(2);
								switch(bits)
								{
									case 0:			///< 0000 0010 0
										tOs = 2; tCs = 5;
										break;
									case 1:			///< 0000 0010 1
										tOs = 1; tCs = 4;
										break;
									case 2:			///< 0000 0011 0
										tOs = 0; tCs = 4;
										break;
									case 3:			///< 0000 0011 1
										tOs = 0; tCs = 3;
										break;
								}//end switch bits...
								numBits = 9;
							}//end if 0000 001...
							else						///< 0000 000
							{
								if(bsr->Read())	///< 0000 0001
								{
									bits = bsr->Read(2);
									switch(bits)
									{
										case 0:			///< 0000 0001 00
											tOs = 3; tCs = 7;
											break;
										case 1:			///< 0000 0001 01
											tOs = 2; tCs = 6;
											break;
										case 2:			///< 0000 0001 10
											tOs = 1; tCs = 5;
											break;
										case 3:			///< 0000 0001 11
											tOs = 0; tCs = 5;
											break;
									}//end switch bits...
									numBits = 10;
								}//end if 0000 0001...
								else						///< 0000 0000
								{
									if(bsr->Read())	///< 0000 0000 1
									{
										bits = bsr->Read(2);
										switch(bits)
										{
											case 0:			///< 0000 0000 100
												tOs = 3; tCs = 8;
												break;
											case 1:			///< 0000 0000 101
												tOs = 2; tCs = 7;
												break;
											case 2:			///< 0000 0000 110
												tOs = 1; tCs = 6;
												break;
											case 3:			///< 0000 0000 111
												tOs = 0; tCs = 6;
												break;
										}//end switch bits...
										numBits = 11;
									}//end if 0000 0000 1...
									else						///< 0000 0000 0
									{
										if(bsr->Read())	///< 0000 0000 01
										{
											bits = bsr->Read(2);
											switch(bits)
											{
												case 0:			///< 0000 0000 0100
													tOs = 2; tCs = 8;
													break;
												case 1:			///< 0000 0000 0101
													tOs = 1; tCs = 8;
													break;
												case 2:			///< 0000 0000 0110
													tOs = 1; tCs = 7;
													break;
												case 3:			///< 0000 0000 0111
													tOs = 0; tCs = 7;
													break;
											}//end switch bits...
											numBits = 12;
										}//end if 0000 0000 01...
										else						///< 0000 0000 00
										{
											bits = bsr->Read(3);
											if(bits == 7)	///< 0000 0000 0011 1
											{
												numBits = 13; tOs = 0; tCs = 8;
											}//end if 0000 0000 00011 1...
										}//end else 0000 0000 00...
									}//end else 0000 0000 0...
								}//end else 0000 0000...
							}//end else 0000 000...
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalCoeffs	= tCs;
	*trailingOnes = tOs;

	return(numBits);
}//end NCneg2.
========== END FILE: CodecUtils/CoeffTokenH264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/CoeffTokenH264VlcDecoder.h ==========
Bundle entry: 23
Original bytes: 3942
Original SHA-256: 8f0f4fdcf3bf79cef9c3b283ba3d21acc223175e2f561d003abc71c8eefb9f84
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CoeffTokenH264VlcDecoder

TAG						: CTH264VD

FILE NAME			: CoeffTokenH264VlcDecoder.h

DESCRIPTION		: A coeff token Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.2 page 200. The 
								trailing ones and total coeffs are combined in this token 
								and is dependent on the neighbouring blocks' total number
								of coeffs. This implementation is implemented with an
								IVlcDecoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _COEFFTOKENH264VLCDECODER_H
#define _COEFFTOKENH264VLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CoeffTokenH264VlcDecoder : public IVlcDecoder
{
public:
	CoeffTokenH264VlcDecoder();
	virtual ~CoeffTokenH264VlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Decode(IBitStreamReader* bsr) { _numCodeBits = 0; return(0); } 

	/// Optional interface implementation.
	/// The 3 symbols represent total coeffs, trailing ones and neighbours' total coeffs, respectively.
	virtual int	Decode3(IBitStreamReader* bsr, int* symbol1, int* symbol2, int* symbol3);

protected:
	/// Private methods.
	int	NC0to1(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);
	int	NC2to3(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);
	int	NC4to7(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);
	int	NC8up(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);
	int	NCneg1(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);
	int	NCneg2(IBitStreamReader* bsr, int* totalCoeffs, int* trailingOnes);

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class CoeffTokenH264VlcDecoder.

#endif	// _COEFFTOKENH264VLCDECODER_H
========== END FILE: CodecUtils/CoeffTokenH264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/CoeffTokenH264VlcEncoder.cpp ==========
Bundle entry: 24
Original bytes: 9809
Original SHA-256: abdd1f6a4ed9f599ad7ffb7ba90b83117c7969059397ae4d0685d2ffe3544b9e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CoeffTokenH264VlcEncoder

TAG						: CTH264VE

FILE NAME			: CoeffTokenH264VlcEncoder.cpp

DESCRIPTION		: A coeff token Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.2 page 200. The 
								trailing ones and total coeffs are combined in this token 
								and is dependent on the neighbouring blocks' total number
								of coeffs. This implementation is implemented with an
								IVlcEncoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "CoeffTokenH264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
CoeffTokenH264VlcEncoder::CoeffTokenH264VlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
}//end constructor.

CoeffTokenH264VlcEncoder::~CoeffTokenH264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode total coeff - trailing ones - neighbour total coeffs symbols.
The 3 param symbols represent total coeffs, trailing ones and neighbours' 
total coeffs, respectively, and are encoded with the number of bits returned.
The _numCodeBits and _bitCode members are set accordingly.
@param symbol1	: Total coeffs for this block
@param symbol2	: Num of trailing ones for this block
@param symbol3	: Total num of coeffs in neighbourhood blocks
@return					: Num of bits in the codeword.
*/
int	CoeffTokenH264VlcEncoder::Encode3(int symbol1, int symbol2, int symbol3)
{
	int totalCoeffs					= symbol1;
	int trailingOnes				= symbol2;
	int numTotNeighborCoeff = symbol3;

	/// Select the table depending on the neighbourhood total number of coeffs.
	switch(numTotNeighborCoeff)
	{
		case 0:
		case 1:
			_numCodeBits	= nC0to1[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nC0to1[trailingOnes][totalCoeffs].codeWord;
			break;
		case 2:
		case 3:
			_numCodeBits	= nC2to3[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nC2to3[trailingOnes][totalCoeffs].codeWord;
			break;
		case 4:
		case 5:
		case 6:
		case 7:
			_numCodeBits	= nC4to7[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nC4to7[trailingOnes][totalCoeffs].codeWord;
			break;
		case -1:
			_numCodeBits	= nCneg1[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nCneg1[trailingOnes][totalCoeffs].codeWord;
			break;
		case -2:
			_numCodeBits	= nCneg2[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nCneg2[trailingOnes][totalCoeffs].codeWord;
			break;
		default:	///< Greater than or equal to 8.
			_numCodeBits	= nC8up[trailingOnes][totalCoeffs].numBits;
			_bitCode			= nC8up[trailingOnes][totalCoeffs].codeWord;
			break;
	}//end switch numTotNeighborCoeff...

	return(_numCodeBits);
}// end Encode3.


/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nC0to1[4][17] = 
{///<	0				 1				2				 3				4				 5				6				 7				8				 9			 10				11			 12				13			 14				15			 16	= totalCoeffs.
	{ { 1, 1}, { 6, 5}, { 8, 7}, { 9, 7}, {10, 7}, {11, 7}, {13,15}, {13,11}, {13, 8}, {14,15}, {14,11}, {15,15}, {15,11}, {16,15}, {16,11}, {16, 7}, {16, 4} },	///< trailingOnes = 0.
	{ { 0, 0}, { 2, 1}, { 6, 4}, { 8, 6}, { 9, 6}, {10, 6}, {11, 6}, {13,14}, {13,10}, {14,14}, {14,10}, {15,14}, {15,10}, {15, 1}, {16,14}, {16,10}, {16, 6} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 3, 1}, { 7, 5}, { 8, 5}, { 9, 5}, {10, 5}, {11, 5}, {13,13}, {13, 9}, {14,13}, {14, 9}, {15,13}, {15, 9}, {16,13}, {16, 9}, {16, 5} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 5, 3}, { 6, 3}, { 7, 4}, { 8, 4}, { 9, 4}, {10, 4}, {11, 4}, {13,12}, {14,12}, {14, 8}, {15,12}, {15, 8}, {16,12}, {16, 8} }		///< trailingOnes = 3.
};

const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nC2to3[4][17] = 
{///<	0				 1				2				 3				4				 5				6				 7				8				 9			 10				11			 12				13			 14				15			 16	= totalCoeffs.
	{ { 2, 3}, { 6,11}, { 6, 7}, { 7, 7}, { 8, 7}, { 8, 4}, { 9, 7}, {11,15}, {11,11}, {12,15}, {12,11}, {12, 8}, {13,15}, {13,11}, {13, 7}, {14, 9}, {14, 7} },	///< trailingOnes = 0.
	{ { 0, 0}, { 2, 2}, { 5, 7}, { 6,10}, { 6, 6}, { 7, 6}, { 8, 6}, { 9, 6}, {11,14}, {11,10}, {12,14}, {12,10}, {13,14}, {13,10}, {14,11}, {14, 8}, {14, 6} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 3, 3}, { 6, 9}, { 6, 5}, { 7, 5}, { 8, 5}, { 9, 5}, {11,13}, {11, 9}, {12,13}, {12, 9}, {13,13}, {13, 9}, {13, 6}, {14,10}, {14, 5} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 4, 5}, { 4, 4}, { 5, 6}, { 6, 8}, { 6, 4}, { 7, 4}, { 9, 4}, {11,12}, {11, 8}, {12,12}, {13,12}, {13, 8}, {13, 1}, {14, 4} }		///< trailingOnes = 3.
};

const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nC4to7[4][17] = 
{///<	0				 1				2				 3				4				 5				6				 7				8				 9			 10				11			 12				13			 14				15			 16	= totalCoeffs.
	{ { 4,15}, { 6,15}, { 6,11}, { 6, 8}, { 7,15}, { 7,11}, { 7, 9}, { 7, 8}, { 8,15}, { 8,11}, { 9,15}, { 9,11}, { 9, 8}, {10,13}, {10, 9}, {10, 5}, {10, 1} },	///< trailingOnes = 0.
	{ { 0, 0}, { 4,14}, { 5,15}, { 5,12}, { 5,10}, { 5, 8}, { 6,14}, { 6,10}, { 7,14}, { 8,14}, { 8,10}, { 9,14}, { 9,10}, { 9, 7}, {10,12}, {10, 8}, {10, 4} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 4,13}, { 5,14}, { 5,11}, { 5, 9}, { 6,13}, { 6, 9}, { 7,13}, { 7,10}, { 8,13}, { 8, 9}, { 9,13}, { 9, 9}, {10,11}, {10, 7}, {10, 3} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 4,12}, { 4,11}, { 4,10}, { 4, 9}, { 4, 8}, { 5,13}, { 6,12}, { 7,12}, { 8,12}, { 8, 8}, { 9,12}, {10,10}, {10, 6}, {10, 2} }		///< trailingOnes = 3.
};

const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nC8up[4][17] = 
{///<	0				 1				2				 3				4				 5				6				 7				8				 9			 10				11			 12				13			 14				15			 16	= totalCoeffs.
	{ { 6, 3}, { 6, 0}, { 6, 4}, { 6, 8}, { 6,12}, { 6,16}, { 6,20}, { 6,24}, { 6,28}, { 6,32}, { 6,36}, { 6,40}, { 6,44}, { 6,48}, { 6,52}, { 6,56}, { 6,60} },	///< trailingOnes = 0.
	{ { 0, 0}, { 6, 1}, { 6, 5}, { 6, 9}, { 6,13}, { 6,17}, { 6,21}, { 6,25}, { 6,29}, { 6,33}, { 6,37}, { 6,41}, { 6,45}, { 6,49}, { 6,53}, { 6,57}, { 6,61} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 6, 6}, { 6,10}, { 6,14}, { 6,18}, { 6,22}, { 6,26}, { 6,30}, { 6,34}, { 6,38}, { 6,42}, { 6,46}, { 6,50}, { 6,54}, { 6,58}, { 6,62} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 6,11}, { 6,15}, { 6,19}, { 6,23}, { 6,27}, { 6,31}, { 6,35}, { 6,39}, { 6,43}, { 6,47}, { 6,51}, { 6,55}, { 6,59}, { 6,63} }		///< trailingOnes = 3.
};

const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nCneg1[4][5] = 
{///<	0				 1				2				 3				4	= totalCoeffs.
	{ { 2, 1}, { 6, 7}, { 6, 4}, { 6, 3}, { 6, 2} },	///< trailingOnes = 0.
	{ { 0, 0}, { 1, 1}, { 6, 6}, { 7, 3}, { 8, 3} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 3, 1}, { 7, 2}, { 8, 2} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 6, 5}, { 7, 0} }		///< trailingOnes = 3.
};

const CTH264VE_VlcCodeType CoeffTokenH264VlcEncoder::nCneg2[4][9] = 
{///<	0				 1				2				 3				4				 5				6				 7				8	= totalCoeffs.
	{ { 1, 1}, { 7,15}, { 7,14}, { 9, 7}, { 9, 6}, {10, 7}, {11, 7}, {12, 7}, {13, 7} },	///< trailingOnes = 0.
	{ { 0, 0}, { 2, 1}, { 7,13}, { 7,12}, { 9, 5}, {10, 6}, {11, 6}, {12, 6}, {12, 5} },	///< trailingOnes = 1.
	{ { 0, 0}, { 0, 0}, { 3, 1}, { 7,11}, { 7,10}, { 9, 4}, {10, 5}, {11, 5}, {12, 4} },	///< trailingOnes = 2.
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 5, 1}, { 6, 1}, { 7, 9}, { 7, 8}, {10, 4}, {11, 4} }		///< trailingOnes = 3.
};

========== END FILE: CodecUtils/CoeffTokenH264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/CoeffTokenH264VlcEncoder.h ==========
Bundle entry: 25
Original bytes: 4302
Original SHA-256: a9a0f5d4593cbbbeddfc2d5c8648b59d37b19b09d4747855d3703386c2cedf5d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: CoeffTokenH264VlcEncoder

TAG						: CTH264VE

FILE NAME			: CoeffTokenH264VlcEncoder.h

DESCRIPTION		: A coeff token Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.2 page 200. The 
								trailing ones and total coeffs are combined in this token 
								and is dependent on the neighbouring blocks' total number
								of coeffs. This implementation is implemented with an
								IVlcEncoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _COEFFTOKENH264VLCENCODER_H
#define _COEFFTOKENH264VLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class constants.
---------------------------------------------------------------------------
*/

/*
---------------------------------------------------------------------------
	Type definitions.
---------------------------------------------------------------------------
*/
typedef struct _CTH264VE_VlcCodeType
{
  int		numBits;	///< Num of bits in code word.
  int		codeWord;	///< Code word bit representation.
} CTH264VE_VlcCodeType;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class CoeffTokenH264VlcEncoder : public IVlcEncoder
{
public:
	CoeffTokenH264VlcEncoder(void);
	virtual ~CoeffTokenH264VlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface implementation.
	/// The 3 symbols represent total coeffs, trailing ones and neighbours' total coeffs, respectively.
	virtual int	Encode3(int symbol1, int symbol2, int symbol3);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

	/// Constants of table sets.
	static const CTH264VE_VlcCodeType nC0to1[4][17];
	static const CTH264VE_VlcCodeType nC2to3[4][17];
	static const CTH264VE_VlcCodeType nC4to7[4][17];
	static const CTH264VE_VlcCodeType nC8up[4][17];
	static const CTH264VE_VlcCodeType nCneg1[4][5];
	static const CTH264VE_VlcCodeType nCneg2[4][9];

};// end class CoeffTokenH264VlcEncoder.

#endif	// end _COEFFTOKENH264VLCENCODER_H.
========== END FILE: CodecUtils/CoeffTokenH264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombSignedVlcDecoder.h ==========
Bundle entry: 26
Original bytes: 3254
Original SHA-256: fe5141ac37c716b6746a83cc1d07d59008d02d57226c01e7a8aa0fd531864336
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombSignedVlcDecoder

TAG						: EGSVD

FILE NAME			: ExpGolombSignedVlcDecoder.h

DESCRIPTION		: An Exp-Golomb Vlc decoder implementation for signed 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.3 page 196. This implementation is implemented 
								with an IVlcDecoder Interface and is an extention of the
								unsigned Exp-Golomb Vlc decoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBSIGNEDVLCDECODER_H
#define _EXPGOLOMBSIGNEDVLCDECODER_H

#include "ExpGolombUnsignedVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombSignedVlcDecoder : public ExpGolombUnsignedVlcDecoder
{
public:
	ExpGolombSignedVlcDecoder(void) {}
	virtual ~ExpGolombSignedVlcDecoder(void){}

public:
	/// A single symbol decoding is the only requirement. Convert
	/// the unsigned symbol input from the base class into a signed 
	/// symbol.
	virtual int Decode(IBitStreamReader* bsr)
	{
		int x = ExpGolombUnsignedVlcDecoder::Decode(bsr);
		if(x != 0)
		{
			if(x & 1)	///< Odd are positive.
				x = (x+1) >> 1;
			else			///< Even are negative.
				x = -(x >> 1);
		}//end if !x...

		return(x);
	}//end Decode...

};// end class ExpGolombSignedVlcDecoder.

#endif	// end _EXPGOLOMBSIGNEDVLCDECODER_H.
========== END FILE: CodecUtils/ExpGolombSignedVlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombSignedVlcEncoder.h ==========
Bundle entry: 27
Original bytes: 3176
Original SHA-256: 9f3b5f282783ba83cb769fd5bc274e80a62eaf422bfa81b8dcefd1f5de658016
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombSignedVlcEncoder

TAG						: EGSVE

FILE NAME			: ExpGolombSignedVlcEncoder.h

DESCRIPTION		: An Exp-Golomb Vlc encoder implementation for signed 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.3 page 196. This implementation is implemented 
								with an IVlcEncoder Interface and is an extention of the
								unsigned Exp-Golomb Vlc encoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBSIGNEDVLCENCODER_H
#define _EXPGOLOMBSIGNEDVLCENCODER_H

#include "ExpGolombUnsignedVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombSignedVlcEncoder : public ExpGolombUnsignedVlcEncoder
{
public:
	ExpGolombSignedVlcEncoder(void) {}
	virtual ~ExpGolombSignedVlcEncoder(void){}

public:
	/// A single symbol encoding is the only requirement. Convert
	/// the signed input into an unsigned symbol before calling the
	/// base class.
	virtual int Encode(int symbol)
	{
		int x = 2*symbol;
		if(x <= 0)
			return(ExpGolombUnsignedVlcEncoder::Encode(-x));
		else
			return(ExpGolombUnsignedVlcEncoder::Encode(x-1));
	}//end Encode...

};// end class ExpGolombSignedVlcEncoder.

#endif	// end _EXPGOLOMBSIGNEDVLCENCODER_H.
========== END FILE: CodecUtils/ExpGolombSignedVlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombTruncVlcDecoder.h ==========
Bundle entry: 28
Original bytes: 3635
Original SHA-256: 7c7f74365c2f3be4199f0b87d7281e542ad8cdaa914b053042f4d0e3f72a6d50
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombTruncVlcDecoder

TAG						: EGTVD

FILE NAME			: ExpGolombTruncVlcDecoder.h

DESCRIPTION		: An Exp-Golomb Vlc decoder implementation for truncated 
								integer symbols as used in H.264 Recommendation (03/2005) 
								described on page 195. This implementation is implemented 
								with an IVlcDecoder Interface and is an extention of the
								unsigned Exp-Golomb Vlc decoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBTRUNCVLCDECODER_H
#define _EXPGOLOMBTRUNCVLCDECODER_H

#include "ExpGolombUnsignedVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombTruncVlcDecoder : public ExpGolombUnsignedVlcDecoder
{
public:
	ExpGolombTruncVlcDecoder(void) {}
	virtual ~ExpGolombTruncVlcDecoder(void){}

public:
	/// There is no single symbol decoding requirement.
	virtual int Decode(IBitStreamReader* bsr) { return(0); }

	/// Optional interface.
public:

	/** Decode with a range [0...range]
	The 2 symbols represent the unsigned decoded value and the expected
	range of the decoded value, respectively.
	@param bsr			: Bit stream to get from.
	@param symbol1	: Reference to returned value.
	@param symbol2	: Range of the value to be decoded (input).
	@return					: Num of bits extracted.
	*/
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
	{
		if( *symbol2 == 1)	///< Range = [0...1]
		{
			_numCodeBits = 1;
			*symbol1 = !bsr->Read();
			return(1);
		}//end if symbol2...

		*symbol1 = ExpGolombUnsignedVlcDecoder::Decode(bsr);
		return(_numCodeBits);
	}//end Decode2...

};// end class ExpGolombTruncVlcDecoder.

#endif	// end _EXPGOLOMBTRUNCVLCDECODER_H.
========== END FILE: CodecUtils/ExpGolombTruncVlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombTruncVlcEncoder.h ==========
Bundle entry: 29
Original bytes: 3487
Original SHA-256: 029738f0ba205326ef422127700d3451f5503c26eb18a49b177b16abd239fa99
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombTruncVlcEncoder

TAG						: EGTVE

FILE NAME			: ExpGolombTruncVlcEncoder.h

DESCRIPTION		: An Exp-Golomb Vlc encoder implementation for truncated 
								integer symbols as used in H.264 Recommendation (03/2005) 
								described on page 195. This implementation is implemented 
								with an IVlcEncoder Interface and is an extention of the
								unsigned Exp-Golomb Vlc encoder.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBTRUNCVLCENCODER_H
#define _EXPGOLOMBTRUNCVLCENCODER_H

#include "ExpGolombUnsignedVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombTruncVlcEncoder : public ExpGolombUnsignedVlcEncoder
{
public:
	ExpGolombTruncVlcEncoder(void) {}
	virtual ~ExpGolombTruncVlcEncoder(void){}

public:
	/// Does not have a single symbol encoding requirement.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface.
public:

	/** Encode with a range [0...range]
	The 2 symbols represent the input value and the range, respectively.
	@param symbol1	: Unsigned value to encode.
	@param symbol2	: Range of the value to encode.
	@return					: Num of bits in the codeword.
	*/
	virtual int	Encode2(int symbol1, int symbol2)
	{
		int x = symbol1;
		if(symbol2 == 1)	///< range = 0...1
		{
			_numCodeBits	= 1;
			_bitCode			= !x;
			return(1);
		}//end if symbol2...

		return(ExpGolombUnsignedVlcEncoder::Encode(x));
	}//end Encode...

};// end class ExpGolombTruncVlcEncoder.

#endif	// end _EXPGOLOMBTRUNCVLCENCODER_H.
========== END FILE: CodecUtils/ExpGolombTruncVlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombUnsignedVlcDecoder.cpp ==========
Bundle entry: 30
Original bytes: 3527
Original SHA-256: 1aa17169548209ef34c2dad736f7469717a65cf38edb14a6b04e4b9795e169c0
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombUnsignedVlcDecoder

TAG						: EGUVD

FILE NAME			: ExpGolombUnsignedVlcDecoder.cpp

DESCRIPTION		: An Exp-Golomb Vlc decoder implementation for unsigned 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.2 page 195. This implementation is implemented 
								with an IVlcDecoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "ExpGolombUnsignedVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
ExpGolombUnsignedVlcDecoder::ExpGolombUnsignedVlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

ExpGolombUnsignedVlcDecoder::~ExpGolombUnsignedVlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode an Exp-Golomb code from the bit stream.
The symbol is extracted from the bit stream and returned.
@param bsr			: Bit stream to get from.
@return					: Symbol extracted.
*/
int	ExpGolombUnsignedVlcDecoder::Decode(IBitStreamReader* bsr)
{
	/// Reset bits extracted.
  _numCodeBits = 0;
	int symbol = 0;

	/// Read leading zeros.
	int leadingZeros = 0;
	while(bsr->Read() == 0)
		leadingZeros++;

	symbol = (1 << leadingZeros) - 1 + bsr->Read(leadingZeros);
	_numCodeBits = leadingZeros*2 + 1;

  return(symbol);
}//end Decode.

========== END FILE: CodecUtils/ExpGolombUnsignedVlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/ExpGolombUnsignedVlcDecoder.h ==========
Bundle entry: 31
Original bytes: 3079
Original SHA-256: 1687b1ade1f26ae837eb234d473361cebb631feb9cbab91540df96503f17ec30
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombUnsignedVlcDecoder

TAG						: EGUVD

FILE NAME			: ExpGolombUnsignedVlcDecoder.h

DESCRIPTION		: An Exp-Golomb Vlc decoder implementation for unsigned 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.2 page 195. This implementation is implemented 
								with an IVlcDecoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBUNSIGNEDVLCDECODER_H
#define _EXPGOLOMBUNSIGNEDVLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombUnsignedVlcDecoder : public IVlcDecoder
{
public:
	ExpGolombUnsignedVlcDecoder();
	virtual ~ExpGolombUnsignedVlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol decoding. Returns the sysmbol.
	virtual int Decode(IBitStreamReader* bsr); 

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class ExpGolombUnsignedVlcDecoder.

#endif	// _EXPGOLOMBUNSIGNEDVLCDECODER_H
========== END FILE: CodecUtils/ExpGolombUnsignedVlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/ExpGolombUnsignedVlcEncoder.cpp ==========
Bundle entry: 32
Original bytes: 4074
Original SHA-256: 633619536afb4173f7c35441df8eeb8cd4095a592bb827adb328470b814ec122
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombUnsignedVlcEncoder

TAG						: EGUVE

FILE NAME			: ExpGolombUnsignedVlcEncoder.cpp

DESCRIPTION		: An Exp-Golomb Vlc encoder implementation for unsigned 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.2 page 195. This implementation is implemented 
								with an IVlcEncoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <math.h>
#include "ExpGolombUnsignedVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
ExpGolombUnsignedVlcEncoder::ExpGolombUnsignedVlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
  _extBitCode   = 0;
}//end constructor.

ExpGolombUnsignedVlcEncoder::~ExpGolombUnsignedVlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode unsigned integer symbol.
The unsigned integer is encoded and the number of bits of the symbol is returned. 
The _numCodeBits and _bitCode members are set accordingly. This implementation
is limited to 32 bit code words (default) with an extension to 64 bit.
@param symbol	:	Unsigned integer to code 
@return				: Num of bits in the codeword.
*/
int	ExpGolombUnsignedVlcEncoder::Encode(int symbol)
{
	_bitCode			= 0;
  _extBitCode   = 0;  ///< Upper 32 bits will always be leading zeros in this implementation.
	_numCodeBits	= 0;

	if(symbol == 0)
	{
		_bitCode			= 1;
		_numCodeBits	= 1;
	}//end if symbol...
	else
	{
		int x = symbol + 1;
		int leadingZeros = (int)(log((double)x)/double(0.69314718055994529));	///< log(2.0) = 0.69314718055994529.
		_numCodeBits = 2*leadingZeros + 1;
		if(_numCodeBits <= 64)
		{
			int a = 1 << leadingZeros;
			_bitCode = (x - a) | a;
		}//end if _numCodeBits...
		else
			_numCodeBits = 0;
	}//end else...

	return(_numCodeBits);
}// end Encode.




========== END FILE: CodecUtils/ExpGolombUnsignedVlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/ExpGolombUnsignedVlcEncoder.h ==========
Bundle entry: 33
Original bytes: 3408
Original SHA-256: f5bc1154c06d0c6c0a436ff5e0c4b18c0de5b246281045e42afa7c807312f6be
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ExpGolombUnsignedVlcEncoder

TAG						: EGUVE

FILE NAME			: ExpGolombUnsignedVlcEncoder.h

DESCRIPTION		: An Exp-Golomb Vlc encoder implementation for unsigned 
								integer symbols as used in H.264 Recommendation (03/2005) 
								Table 9.2 page 195. This implementation is implemented 
								with an IVlcEncoder Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _EXPGOLOMBUNSIGNEDVLCENCODER_H
#define _EXPGOLOMBUNSIGNEDVLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class ExpGolombUnsignedVlcEncoder : public IVlcEncoder
{
public:
	ExpGolombUnsignedVlcEncoder(void);
	virtual ~ExpGolombUnsignedVlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
  /// For extended codes of greater than 32 bits but less than 64 bits. _bitCode
  /// holds the lower 32 bits and _extBitCode the upper 32 bits.
  int GetExtCode(void)      { return(_extBitCode); }
	/// A single symbol encoding is the only requirement.
	virtual int Encode(int symbol);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The lower 32 bits of code of length numCodeBits or 32.
  int   _extBitCode;  ///< The upper 32 bits of code of length 0 or numCodeBits - 32.

};// end class ExpGolombUnsignedVlcEncoder.

#endif	// end _EXPGOLOMBUNSIGNEDVLCENCODER_H.
========== END FILE: CodecUtils/ExpGolombUnsignedVlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/FastForward4x4ITImpl1.cpp ==========
Bundle entry: 34
Original bytes: 8288
Original SHA-256: f02049da1440c8eaba5034002e8672bb84e0c283933009ab4a0b6e78a1eb3c32
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4ITImpl1

TAG						: FF4ITI1

FILE NAME			: FastForward4x4ITImpl1.cpp

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

======================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastForward4x4ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastForward4x4ITImpl1::NormAdjust[6][3] =
{
	{13107, 5243, 8066 },
	{11916, 4660, 7490 },
	{10082, 4194, 6554 },
	{ 9362, 3647, 5825 },
	{ 8192, 3355, 5243 },
	{ 7282, 2893, 4559 }
};

const int FastForward4x4ITImpl1::ColSelector[16] =
{
	0, 2, 0, 2 ,
	2, 1, 2, 1 ,
	0, 2, 0, 2 ,
	2, 1, 2, 1 
};

FastForward4x4ITImpl1::FastForward4x4ITImpl1()	
{ 
	_mode		= TransformAndQuant; 
	_intra	= 1;
	_q			= 1;
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;
}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place forward Integer Transform.
The 2-D IT is performed on the input and replaces it with the coeffs. A 1-D
transform is performed on the rows first and then the cols.
@param ptr	: Data to transform.
@return			:	none.
*/
void FastForward4x4ITImpl1::Transform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	/// Only do IT modes = 0 & 1.
	if(_mode != QuantOnly)	///< 2 = Q only.
	{
		/// 1-D forward horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+2]	= (short)(s0 - s1);
			block[j+1]	= (short)(s2 + (s3 << 1));
			block[j+3]	= (short)(s3 - (s2 << 1));
		}//end for j...

		/// 1-D forward vert direction.

		if(_mode == TransformAndQuant)	///< 0 = IT+Q.
		{
			for(j = 0; j < 4; j++)
			{
				/// 1st stage transform.
				int s0 = (int)block[j]		+ (int)block[j+12];
				int s3 = (int)block[j]		- (int)block[j+12];
				int s1 = (int)block[j+4]	+ (int)block[j+8];
				int s2 = (int)block[j+4]	- (int)block[j+8];

				/// 2nd stage transform with scaling and quantisation.
				int x0 = s0 + s1;
				int r	= ColSelector[j];
				if(x0 < 0)
					block[j] = (short)(-( (((-x0) * NormAdjust[_qm][r]) + _f) >> _scale ));
				else
					block[j] = (short)( ((x0 * NormAdjust[_qm][r]) + _f) >> _scale );

				int x2 = s0 - s1;
				r	= ColSelector[j+8];
				if(x2 < 0)
					block[j+8] = (short)(-( (((-x2) * NormAdjust[_qm][r]) + _f) >> _scale ));
				else
					block[j+8] = (short)( ((x2 * NormAdjust[_qm][r]) + _f) >> _scale );

				int x1 = s2 + (s3 << 1);
				r	= ColSelector[j+4];
				if(x1 < 0)
					block[j+4] = (short)(-( (((-x1) * NormAdjust[_qm][r]) + _f) >> _scale ));
				else
					block[j+4] = (short)( ((x1 * NormAdjust[_qm][r]) + _f) >> _scale );

				int x3 = s3 - (s2 << 1);
				r	= ColSelector[j+12];
				if(x3 < 0)
					block[j+12] = (short)(-( (((-x3) * NormAdjust[_qm][r]) + _f) >> _scale ));
				else
					block[j+12] = (short)( ((x3 * NormAdjust[_qm][r]) + _f) >> _scale );
			}//end for j...
		}//end if _mode...
		else	///< mode = 1 i.e. IT only.
		{
			for(j = 0; j < 4; j++)
			{
				/// 1st stage transform.
				int s0 = (int)(block[j]		+ block[j+12]);
				int s3 = (int)(block[j]		- block[j+12]);
				int s1 = (int)(block[j+4] + block[j+8]);
				int s2 = (int)(block[j+4] - block[j+8]);

				/// 2nd stage transform.
				block[j]		= (short)(s0 + s1);
				block[j+8]	= (short)(s0 - s1);
				block[j+4]	= (short)(s2 + (s3 << 1));
				block[j+12]	= (short)(s3 - (s2 << 1));
			}//end for j...
		}//end else...
	}//end if _mode != 2...
	else ///< mode = 2 i.e. QuantOnly.
	{
		/// Scaling and quantisation are combined.
		int i;
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int x = (int)block[i*4 + j];
				int r = ColSelector[i*4 + j];
				if( x < 0 )
					block[i*4 + j] = (short)(-( (((-x) * NormAdjust[_qm][r]) + _f) >> _scale ));
				else
					block[i*4 + j] = (short)( ((x * NormAdjust[_qm][r]) + _f) >> _scale );
			}//end for i & j...
	}//end else...

}//end Transform.

/** Transfer forward IT.
The IT is performed on the input and the coeffs are written to 
the output.
@param pIn		: Input data.
@param pCoeff	: Output coeffs.
@return				:	none.
*/
void FastForward4x4ITImpl1::Transform(void* pIn, void* pCoeff)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pCoeff, pIn, sizeof(short) * 16);
	Transform(pCoeff);
}//end Transform.

/** Set and get parameters for the implementation.
An Intra and Inter parameter and quantisation parameter are the only 
requirement for this implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastForward4x4ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_q = paramVal;
          SetNewQP();
				}//end if q...
			}//end case QUANT_ID...
			break;
		case INTRA_FLAG_ID:
			_intra = paramVal;
      SetNewQP();
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastForward4x4ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		case INTRA_FLAG_ID:
			ret = _intra;
			break;
		default :
			ret = _intra;	///< Intra flag is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.

/** Set internal quant members based on _q.
@return: none.
*/
void FastForward4x4ITImpl1::SetNewQP(void)
{
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;
}//end SetNewQP.
========== END FILE: CodecUtils/FastForward4x4ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastForward4x4ITImpl1.h ==========
Bundle entry: 35
Original bytes: 5360
Original SHA-256: 3679254049a6a3a6bd29a0d504dbd3a9cee3937f9b8db460b798eddee44ef162
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4ITImpl1

TAG						: FF4ITI1

FILE NAME			: FastForward4x4ITImpl1.h

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								transform defined by the H.264 standard on the input. 
								It implements the IForwardTransform interface. The 
								scaling	is part of the quantisation process.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================================
*/
#ifndef _FASTFORWARD4X4ITIMPL1_H
#define _FASTFORWARD4X4ITIMPL1_H

#pragma once

#include "IForwardTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastForward4x4ITImpl1 : public IForwardTransform
{
	public:
		FastForward4x4ITImpl1();
		virtual ~FastForward4x4ITImpl1()	{ }

	// Interface implementation.
	public:
		/** In-place forward IT.
		The IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void Transform(void* ptr);

		/** Transfer forward IT.
		The IT is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void Transform(void* pIn, void* pCoeff);

		/** Set scaling array.
		Each coefficient may be scaled after transforming and therefore 
		requires setting up. Only the default scaling is used and 
		therefore this method is not implemented.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale) { }
		virtual void* GetScale(void) { return(NULL); }

		/** Set/Get the mode of operation.
		The modes for this implementation set the combinations of 
		including or excluding the transform with or without quantisation.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		An Intra and Inter parameter and the quantisation parameter are the 
		only requirement for this	implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

    /** Quantise a single value in a block.
    Implement quantising a value in a specified position of the coeffs at a
    specified QP value.
    @param val  : Value to quantise.
    @param pos  : Postion of value in 1-D array of 2-D data.
    @param qp   : Quant param to use.
    @return     : Result of quntisation.
    */
    virtual int QuantiseValue(short val, int pos, int qp) { return(0); }

    /// Internal methods
  private:
    /** Set internal quant members based on _q.
    @return: none.
    */
    void SetNewQP(void);

		/// Constants.
	protected:
		static const int NormAdjust[6][3];
		static const int ColSelector[16];

	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.
		int _intra;	///< 0 = Inter, 1 = Intra.

		/// Hold these members that will only change when q changes.
		int	_q;				///< Current quantisation parameter.
		int	_qm;			///< _q % 6.
		int _qe;			///< _q / 6.
		int _f;				///< Rounding shift = (1 << (15+_qe))/6.
		int _scale;		///< Scaling shift = 15+_qe;

};// end class FastForward4x4ITImpl1.

#endif	//_FASTFORWARD4X4ITIMPL1_H
========== END FILE: CodecUtils/FastForward4x4ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastForward4x4ITImpl2.cpp ==========
Bundle entry: 36
Original bytes: 21471
Original SHA-256: 2b774e4a654712f3d63a5080de882d1f227fb508e46f69e3dd04e345e74f9950
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4ITImpl2

TAG						: FF4ITI2

FILE NAME			: FastForward4x4ITImpl2.cpp

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer

COPYRIGHT			: (c)CSIR 2007-2011 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

======================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastForward4x4ITImpl2.h"

#define FF4ITI2_UNROLL_LOOPS_AND_INTERLEAVE

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastForward4x4ITImpl2::NormAdjust[6][3] =
{
	{13107, 5243, 8066 },
	{11916, 4660, 7490 },
	{10082, 4194, 6554 },
	{ 9362, 3647, 5825 },
	{ 8192, 3355, 5243 },
	{ 7282, 2893, 4559 }
};

const int FastForward4x4ITImpl2::ColSelector[16] =
{
	0, 2, 0, 2 ,
	2, 1, 2, 1 ,
	0, 2, 0, 2 ,
	2, 1, 2, 1 
};

/*
---------------------------------------------------------------------------
	Construction.
---------------------------------------------------------------------------
*/
FastForward4x4ITImpl2::FastForward4x4ITImpl2()	
{ 
	_mode		    = TransformAndQuant; 
	_intra	    = 1;
	_q			= 1;
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;

}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place forward Integer Transform.
The 2-D IT is performed on the input and replaces it with the coeffs. A 1-D
transform is performed on the rows first and then the cols.
@param ptr	: Data to transform.
@return			:	none.
*/
#ifdef FF4ITI2_UNROLL_LOOPS_AND_INTERLEAVE

void FastForward4x4ITImpl2::Transform(void* ptr)
{
	short* block = (short *)ptr;

	if(_mode == IForwardTransform::TransformOnly)
	{
		register int s0,s1,s2,s3;
		register int v0,v1,v2,v3;
		register int r0,r1,r2,r3;
		register int u0,u1,u2,u3;

		/// 1-D forward horiz direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	 + block[3]);
		s3 = (int)(block[0]	 - block[3]);
		s1 = (int)(block[1]  + block[2]);
		s2 = (int)(block[1]  - block[2]);
		v0 = (int)(block[4]	 + block[7]);
		v3 = (int)(block[4]	 - block[7]);
		v1 = (int)(block[5]  + block[6]);
		v2 = (int)(block[5]  - block[6]);
		r0 = (int)(block[8]	 + block[11]);
		r3 = (int)(block[8]	 - block[11]);
		r1 = (int)(block[9]  + block[10]);
		r2 = (int)(block[9]  - block[10]);
		u0 = (int)(block[12] + block[15]);
		u3 = (int)(block[12] - block[15]);
		u1 = (int)(block[13] + block[14]);
		u2 = (int)(block[13] - block[14]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(s2 + (s3 << 1));
		block[2]	= (short)(s0 - s1);
		block[3]	= (short)(s3 - (s2 << 1));
		block[4]	= (short)(v0 + v1);
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(v0 - v1);
		block[7]	= (short)(v3 - (v2 << 1));
		block[8]	= (short)(r0 + r1);
		block[9]	= (short)(r2 + (r3 << 1));
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(r3 - (r2 << 1));
		block[12]	= (short)(u0 + u1);
		block[13]	= (short)(u2 + (u3 << 1));
		block[14]	= (short)(u0 - u1);
		block[15]	= (short)(u3 - (u2 << 1));

		/// 1-D forward vert direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	+ block[12]);
		s3 = (int)(block[0]	- block[12]);
		v0 = (int)(block[1]	+ block[13]);
		v3 = (int)(block[1]	- block[13]);
		r0 = (int)(block[2]	+ block[14]);
		r3 = (int)(block[2]	- block[14]);
		u0 = (int)(block[3]	+ block[15]);
		u3 = (int)(block[3]	- block[15]);
		s1 = (int)(block[4] + block[8]);
		s2 = (int)(block[4] - block[8]);
		v1 = (int)(block[5] + block[9]);
		v2 = (int)(block[5] - block[9]);
		r1 = (int)(block[6] + block[10]);
		r2 = (int)(block[6] - block[10]);
		u1 = (int)(block[7] + block[11]);
		u2 = (int)(block[7] - block[11]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(v0 + v1);
		block[2]	= (short)(r0 + r1);
		block[3]	= (short)(u0 + u1);
		block[4]	= (short)(s2 + (s3 << 1));
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(r2 + (r3 << 1));
		block[7]	= (short)(u2 + (u3 << 1));
		block[8]	= (short)(s0 - s1);
		block[9]	= (short)(v0 - v1);
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(u0 - u1);
		block[12]	= (short)(s3 - (s2 << 1));
		block[13]	= (short)(v3 - (v2 << 1));
		block[14]	= (short)(r3 - (r2 << 1));
		block[15]	= (short)(u3 - (u2 << 1));

	}//end if TransformOnly...
	else if(_mode == IForwardTransform::QuantOnly)
	{
		/// Scaling and quantisation are combined.
		const int* pNorm = NormAdjust[_qm];

		/// [0]
		if( block[0] >= 0 )
			block[0] = (short)( (((int)block[0] * pNorm[0]) + _f) >> _scale );
		else
			block[0] = (short)(-( (((-(int)block[0]) * pNorm[0]) + _f) >> _scale ));
		/// [1]
		if( block[1] >= 0 )
			block[1] = (short)( (((int)block[1] * pNorm[2]) + _f) >> _scale );
		else
			block[1] = (short)(-( (((-(int)block[1]) * pNorm[2]) + _f) >> _scale ));
		/// [2]
		if( block[2] >= 0 )
			block[2] = (short)( (((int)block[2] * pNorm[0]) + _f) >> _scale );
		else
			block[2] = (short)(-( (((-(int)block[2]) * pNorm[0]) + _f) >> _scale ));
		/// [3]
		if( block[3] >= 0 )
			block[3] = (short)( (((int)block[3] * pNorm[2]) + _f) >> _scale );
		else
			block[3] = (short)(-( (((-(int)block[3]) * pNorm[2]) + _f) >> _scale ));
		/// [4]
		if( block[4] >= 0 )
			block[4] = (short)( (((int)block[4] * pNorm[2]) + _f) >> _scale );
		else
			block[4] = (short)(-( (((-(int)block[4]) * pNorm[2]) + _f) >> _scale ));
		/// [5]
		if( block[5] >= 0 )
			block[5] = (short)( (((int)block[5] * pNorm[1]) + _f) >> _scale );
		else
			block[5] = (short)(-( (((-(int)block[5]) * pNorm[1]) + _f) >> _scale ));
		/// [6]
		if( block[6] >= 0 )
			block[6] = (short)( (((int)block[6] * pNorm[2]) + _f) >> _scale );
		else
			block[6] = (short)(-( (((-(int)block[6]) * pNorm[2]) + _f) >> _scale ));
		/// [7]
		if( block[7] >= 0 )
			block[7] = (short)( (((int)block[7] * pNorm[1]) + _f) >> _scale );
		else
			block[7] = (short)(-( (((-(int)block[7]) * pNorm[1]) + _f) >> _scale ));
		/// [8]
		if( block[8] >= 0 )
			block[8] = (short)( (((int)block[8] * pNorm[0]) + _f) >> _scale );
		else
			block[8] = (short)(-( (((-(int)block[8]) * pNorm[0]) + _f) >> _scale ));
		/// [9]
		if( block[9] >= 0 )
			block[9] = (short)( (((int)block[9] * pNorm[2]) + _f) >> _scale );
		else
			block[9] = (short)(-( (((-(int)block[9]) * pNorm[2]) + _f) >> _scale ));
		/// [10]
		if( block[10] >= 0 )
			block[10] = (short)( (((int)block[10] * pNorm[0]) + _f) >> _scale );
		else
			block[10] = (short)(-( (((-(int)block[10]) * pNorm[0]) + _f) >> _scale ));
		/// [11]
		if( block[11] >= 0 )
			block[11] = (short)( (((int)block[11] * pNorm[2]) + _f) >> _scale );
		else
			block[11] = (short)(-( (((-(int)block[11]) * pNorm[2]) + _f) >> _scale ));
		/// [12]
		if( block[12] >= 0 )
			block[12] = (short)( (((int)block[12] * pNorm[2]) + _f) >> _scale );
		else
			block[12] = (short)(-( (((-(int)block[12]) * pNorm[2]) + _f) >> _scale ));
		/// [13]
		if( block[13] >= 0 )
			block[13] = (short)( (((int)block[13] * pNorm[1]) + _f) >> _scale );
		else
			block[13] = (short)(-( (((-(int)block[13]) * pNorm[1]) + _f) >> _scale ));
		/// [14]
		if( block[14] >= 0 )
			block[14] = (short)( (((int)block[14] * pNorm[2]) + _f) >> _scale );
		else
			block[14] = (short)(-( (((-(int)block[14]) * pNorm[2]) + _f) >> _scale ));
		/// [15]
		if( block[15] >= 0 )
			block[15] = (short)( (((int)block[15] * pNorm[1]) + _f) >> _scale );
		else
			block[15] = (short)(-( (((-(int)block[15]) * pNorm[1]) + _f) >> _scale ));

	}//end if QuantOnly...
	else ///< if (_mode == IForwardTransform::TransformAndQuant)
	{
		register int s0,s1,s2,s3;
		register int v0,v1,v2,v3;
		register int r0,r1,r2,r3;
		register int u0,u1,u2,u3;

		/// 1-D forward horiz direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	 + block[3]);
		s3 = (int)(block[0]	 - block[3]);
		s1 = (int)(block[1]  + block[2]);
		s2 = (int)(block[1]  - block[2]);
		v0 = (int)(block[4]	 + block[7]);
		v3 = (int)(block[4]	 - block[7]);
		v1 = (int)(block[5]  + block[6]);
		v2 = (int)(block[5]  - block[6]);
		r0 = (int)(block[8]	 + block[11]);
		r3 = (int)(block[8]	 - block[11]);
		r1 = (int)(block[9]  + block[10]);
		r2 = (int)(block[9]  - block[10]);
		u0 = (int)(block[12] + block[15]);
		u3 = (int)(block[12] - block[15]);
		u1 = (int)(block[13] + block[14]);
		u2 = (int)(block[13] - block[14]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(s2 + (s3 << 1));
		block[2]	= (short)(s0 - s1);
		block[3]	= (short)(s3 - (s2 << 1));
		block[4]	= (short)(v0 + v1);
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(v0 - v1);
		block[7]	= (short)(v3 - (v2 << 1));
		block[8]	= (short)(r0 + r1);
		block[9]	= (short)(r2 + (r3 << 1));
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(r3 - (r2 << 1));
		block[12]	= (short)(u0 + u1);
		block[13]	= (short)(u2 + (u3 << 1));
		block[14]	= (short)(u0 - u1);
		block[15]	= (short)(u3 - (u2 << 1));

		/// 1-D forward vert direction.

		/// 1-D forward vert direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	+ block[12]);
		s3 = (int)(block[0]	- block[12]);
		v0 = (int)(block[1]	+ block[13]);
		v3 = (int)(block[1]	- block[13]);
		r0 = (int)(block[2]	+ block[14]);
		r3 = (int)(block[2]	- block[14]);
		u0 = (int)(block[3]	+ block[15]);
		u3 = (int)(block[3]	- block[15]);
		s1 = (int)(block[4] + block[8]);
		s2 = (int)(block[4] - block[8]);
		v1 = (int)(block[5] + block[9]);
		v2 = (int)(block[5] - block[9]);
		r1 = (int)(block[6] + block[10]);
		r2 = (int)(block[6] - block[10]);
		u1 = (int)(block[7] + block[11]);
		u2 = (int)(block[7] - block[11]);

		/// 2nd stage transform.

		const int* pNorm = NormAdjust[_qm];

		/// [0]
		if( (s0 + s1) >= 0 )
			block[0] = (short)( (((s0 + s1) * pNorm[0]) + _f) >> _scale );
		else
			block[0] = (short)(-( (((-(s0 + s1)) * pNorm[0]) + _f) >> _scale ));
		/// [1]
		if( (v0 + v1) >= 0 )
			block[1] = (short)( (((v0 + v1) * pNorm[2]) + _f) >> _scale );
		else
			block[1] = (short)(-( (((-(v0 + v1)) * pNorm[2]) + _f) >> _scale ));
		/// [2]
		if( (r0 + r1) >= 0 )
			block[2] = (short)( (((r0 + r1) * pNorm[0]) + _f) >> _scale );
		else
			block[2] = (short)(-( (((-(r0 + r1)) * pNorm[0]) + _f) >> _scale ));
		/// [3]
		if( (u0 + u1) >= 0 )
			block[3] = (short)( (((u0 + u1) * pNorm[2]) + _f) >> _scale );
		else
			block[3] = (short)(-( (((-(u0 + u1)) * pNorm[2]) + _f) >> _scale ));

		/// [4]
		register int x4	= s2 + (s3 << 1);
		if( x4 >= 0 )
			block[4] = (short)( ((x4 * pNorm[2]) + _f) >> _scale );
		else
			block[4] = (short)(-( (((-x4) * pNorm[2]) + _f) >> _scale ));
		/// [5]
		register int x5	= v2 + (v3 << 1);
		if( x5 >= 0 )
			block[5] = (short)( ((x5 * pNorm[1]) + _f) >> _scale );
		else
			block[5] = (short)(-( (((-x5) * pNorm[1]) + _f) >> _scale ));
		/// [6]
		register int x6	= r2 + (r3 << 1);
		if( x6 >= 0 )
			block[6] = (short)( ((x6 * pNorm[2]) + _f) >> _scale );
		else
			block[6] = (short)(-( (((-x6) * pNorm[2]) + _f) >> _scale ));
		/// [7]
		register int x7	= u2 + (u3 << 1);
		if( x7 >= 0 )
			block[7] = (short)( ((x7 * pNorm[1]) + _f) >> _scale );
		else
			block[7] = (short)(-( (((-x7) * pNorm[1]) + _f) >> _scale ));

		/// [8]
		if( (s0 - s1) >= 0 )
			block[8] = (short)( (((s0 - s1) * pNorm[0]) + _f) >> _scale );
		else
			block[8] = (short)(-( (((-(s0 - s1)) * pNorm[0]) + _f) >> _scale ));
		/// [9]
		if( (v0 - v1) >= 0 )
			block[9] = (short)( (((v0 - v1) * pNorm[2]) + _f) >> _scale );
		else
			block[9] = (short)(-( (((-(v0 - v1)) * pNorm[2]) + _f) >> _scale ));
		/// [10]
		if( (r0 - r1) >= 0 )
			block[10] = (short)( (((r0 - r1) * pNorm[0]) + _f) >> _scale );
		else
			block[10] = (short)(-( (((-(r0 - r1)) * pNorm[0]) + _f) >> _scale ));
		/// [11]
		if( (u0 - u1) >= 0 )
			block[11] = (short)( (((u0 - u1) * pNorm[2]) + _f) >> _scale );
		else
			block[11] = (short)(-( (((-(u0 - u1)) * pNorm[2]) + _f) >> _scale ));

		/// [12]
		register int x12	= s3 - (s2 << 1);
		if( x12 >= 0 )
			block[12] = (short)( ((x12 * pNorm[2]) + _f) >> _scale );
		else
			block[12] = (short)(-( (((-x12) * pNorm[2]) + _f) >> _scale ));
		/// [13]
		register int x13	= v3 - (v2 << 1);
		if( x13 >= 0 )
			block[13] = (short)( ((x13 * pNorm[1]) + _f) >> _scale );
		else
			block[13] = (short)(-( (((-x13) * pNorm[1]) + _f) >> _scale ));
		/// [14]
		register int x14	= r3 - (r2 << 1);
		if( x14 >= 0 )
			block[14] = (short)( ((x14 * pNorm[2]) + _f) >> _scale );
		else
			block[14] = (short)(-( (((-x14) * pNorm[2]) + _f) >> _scale ));
		/// [15]
		register int x15	= u3 - (u2 << 1);
		if( x15 >= 0 )
			block[15] = (short)( ((x15 * pNorm[1]) + _f) >> _scale );
		else
			block[15] = (short)(-( (((-x15) * pNorm[1]) + _f) >> _scale ));

	}//end else...

}//end Transform.

#else ///< !FF4ITI2_UNROLL_LOOPS_AND_INTERLEAVE

void FastForward4x4ITImpl2::Transform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	if(_mode == IForwardTransform::TransformOnly)
	{
		/// 1-D forward horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+1]	= (short)(s2 + (s3 << 1));
			block[j+2]	= (short)(s0 - s1);
			block[j+3]	= (short)(s3 - (s2 << 1));
		}//end for j...

		/// 1-D forward vert direction.
		for(j = 0; j < 4; j++)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+12]);
			int s3 = (int)(block[j]		- block[j+12]);
			int s1 = (int)(block[j+4] + block[j+8]);
			int s2 = (int)(block[j+4] - block[j+8]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+4]	= (short)(s2 + (s3 << 1));
			block[j+8]	= (short)(s0 - s1);
			block[j+12]	= (short)(s3 - (s2 << 1));
		}//end for j...

	}//end if TransformOnly...
	else if(_mode == IForwardTransform::QuantOnly)
	{
		/// Scaling and quantisation are combined.
		const int* pNorm = NormAdjust[_qm];

		for(j = 0; j < 16; j++)
		{
			if( block[j] >= 0 )
				block[j] = (short)( (((int)block[j] * pNorm[ColSelector[j]]) + _f) >> _scale );
			else
				block[j] = (short)(-( (((-(int)block[j]) * pNorm[ColSelector[j]]) + _f) >> _scale ));
		}//end for j...
	}//end if QuantOnly...
	else ///< if (_mode == IForwardTransform::TransformAndQuant)
	{
		const int* pNorm = NormAdjust[_qm];

		/// 1-D forward horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+1]	= (short)(s2 + (s3 << 1));
			block[j+2]	= (short)(s0 - s1);
			block[j+3]	= (short)(s3 - (s2 << 1));
		}//end for j...

		/// 1-D forward vert direction.
		for(j = 0; j < 4; j++)
		{
			/// 1st stage transform.
			int s0 = (int)block[j]		+ (int)block[j+12];
			int s3 = (int)block[j]		- (int)block[j+12];
			int s1 = (int)block[j+4]	+ (int)block[j+8];
			int s2 = (int)block[j+4]	- (int)block[j+8];

			/// 2nd stage transform with scaling and quantisation.
			int x0 = s0 + s1;
			int x1 = s2 + (s3 << 1);
			int x2 = s0 - s1;
			int x3 = s3 - (s2 << 1);

			if(x0 < 0)
				block[j] = (short)(-( (((-x0) * pNorm[ColSelector[j]]) + _f) >> _scale ));
			else
				block[j] = (short)( ((x0 * pNorm[ColSelector[j]]) + _f) >> _scale );

			if(x1 < 0)
				block[j+4] = (short)(-( (((-x1) * pNorm[ColSelector[j+4]]) + _f) >> _scale ));
			else
				block[j+4] = (short)( ((x1 * pNorm[ColSelector[j+4]]) + _f) >> _scale );

			if(x2 < 0)
				block[j+8] = (short)(-( (((-x2) * pNorm[ColSelector[j+8]]) + _f) >> _scale ));
			else
				block[j+8] = (short)( ((x2 * pNorm[ColSelector[j+8]]) + _f) >> _scale );

			if(x3 < 0)
				block[j+12] = (short)(-( (((-x3) * pNorm[ColSelector[j+12]]) + _f) >> _scale ));
			else
				block[j+12] = (short)( ((x3 * pNorm[ColSelector[j+12]]) + _f) >> _scale );
		}//end for j...
	}//end else...

}//end Transform.

#endif 

/** Transfer forward IT.
The IT is performed on the input and the coeffs are written to 
the output.
@param pIn		: Input data.
@param pCoeff	: Output coeffs.
@return				:	none.
*/
void FastForward4x4ITImpl2::Transform(void* pIn, void* pCoeff)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pCoeff, pIn, sizeof(short) * 16);
	Transform(pCoeff);
}//end Transform.

/** Set and get parameters for the implementation.
An Intra and Inter parameter and quantisation parameter are the only 
requirement for this implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastForward4x4ITImpl2::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_q = paramVal;
          SetNewQP();
				}//end if q...
			}//end case QUANT_ID...
			break;
		case INTRA_FLAG_ID:
			_intra = paramVal;
      SetNewQP();
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastForward4x4ITImpl2::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		case INTRA_FLAG_ID:
			ret = _intra;
			break;
		default :
			ret = _intra;	///< Intra flag is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.

/** Quantise a single value in a block.
Implement quantising a value in a specified position of the coeffs at a
specified QP value.
@param val  : Value to quantise.
@param pos  : Postion of value in 1-D array of 2-D data.
@param qp   : Quant param to use.
@return     : Result of quantisation.
*/
int FastForward4x4ITImpl2::QuantiseValue(short val, int pos, int qp)
{
  _q = qp;
  SetNewQP();

  int norm = 0;
  switch(pos)
  {
    /*  By default norm is 0.
    case 0:
    case 2:
    case 8:
    case 10:
      norm = 0;
      break;
    */

    case 5:
    case 7:
    case 13:
    case 15:
      norm = 1;
      break;

    case 1:
    case 3:
    case 4:
    case 6:
    case 9:
    case 11:
    case 12:
    case 14:
      norm = 2;
      break;
  }//end switch...

  short quantVal = 0;
	if( val >= 0 )
		quantVal = (short)( (((int)val * NormAdjust[_qm][norm]) + _f) >> _scale );
	else
		quantVal = (short)(-( (((-(int)val) * NormAdjust[_qm][norm]) + _f) >> _scale ));

  return((int)quantVal);
}//end QuantiseValue. 

/** Set internal quant members based on _q.
@return: none.
*/
void FastForward4x4ITImpl2::SetNewQP(void)
{
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;
}//end SetNewQP.
========== END FILE: CodecUtils/FastForward4x4ITImpl2.cpp ==========

========== BEGIN FILE: CodecUtils/FastForward4x4ITImpl2.h ==========
Bundle entry: 37
Original bytes: 5373
Original SHA-256: 0cc3126389ef101cce400ed364da802e04654581fb5f05638221d66ffd5911b3
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4ITImpl2

TAG						: FF4ITI2

FILE NAME			: FastForward4x4ITImpl2.h

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								transform defined by the H.264 standard on the input. 
								It implements the IForwardTransform interface. The 
								scaling	is part of the quantisation process.

COPYRIGHT			: (c)CSIR 2007-2020 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================================
*/
#ifndef _FASTFORWARD4X4ITIMPL2_H
#define _FASTFORWARD4X4ITIMPL2_H

#pragma once

#include "IForwardTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastForward4x4ITImpl2 : public IForwardTransform
{
	public:
		FastForward4x4ITImpl2();
		virtual ~FastForward4x4ITImpl2()	{ }

	// Interface implementation.
	public:
		/** In-place forward IT.
		The IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void Transform(void* ptr);

		/** Transfer forward IT.
		The IT is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void Transform(void* pIn, void* pCoeff);

		/** Set scaling array.
		Each coefficient may be scaled after transforming and therefore 
		requires setting up. Only the default scaling is used and 
		therefore this method is not implemented.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale) { }
		virtual void* GetScale(void) { return(NULL); }

		/** Set/Get the mode of operation.
		The modes for this implementation set the combinations of 
		including or excluding the transform with or without quantisation.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		An Intra and Inter parameter and the quantisation parameter are the 
		only requirement for this	implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

    /** Quantise a single value in a block.
    Implement quantising a value in a specified position of the coeffs at a
    specified QP value.
    @param val  : Value to quantise.
    @param pos  : Postion of value in 1-D array of 2-D data.
    @param qp   : Quant param to use.
    @return     : Result of quantisation.
    */
    virtual int QuantiseValue(short val, int pos, int qp);

    /// Internal methods
  private:
    /** Set internal quant members based on _q.
    @return: none.
    */
    void SetNewQP(void);

		/// Constants.
	protected:
		static const int NormAdjust[6][3];
		static const int ColSelector[16];

	protected:
		int _mode;	      ///< 0 = IT+Q, 1 = IT only, 2 = Q only.
		int _intra;	      ///< 0 = Inter, 1 = Intra.

		/// Hold these members that will only change when q or intra flag changes.
		int	_q;				///< Current quantisation parameter.
		int	_qm;			///< _q % 6.
		int _qe;			///< _q / 6.
		int _f;				///< Rounding shift = (1 << (15+_qe))/6.
		int _scale;		///< Scaling shift = 15+_qe;

};// end class FastForward4x4ITImpl2.

#endif	//_FASTFORWARD4X4ITIMPL2_H
========== END FILE: CodecUtils/FastForward4x4ITImpl2.h ==========

========== BEGIN FILE: CodecUtils/FastForward4x4On16x16ITImpl1.cpp ==========
Bundle entry: 38
Original bytes: 26933
Original SHA-256: bfb4ce4a72c3ebb0a984b53d5303d1ad6f41e55166f8df01982c88a9a46467cf
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4On16x16ITImpl1

TAG						: FF4O16ITI2

FILE NAME			: FastForward4x4On16x16ITImpl1.cpp

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								transform defined by the H.264 standard on the 16x16
                macroblock input. It implements the IForwardTransform 
                interface. The scaling	is part of the quantisation process.

COPYRIGHT			: (c)CSIR 2007-2011 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

======================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastForward4x4On16x16ITImpl1.h"

//#define FF4O16ITI2_UNROLL_LOOPS_AND_INTERLEAVE

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastForward4x4On16x16ITImpl1::NormAdjust[6][3] =
{
	{13107, 5243, 8066 },
	{11916, 4660, 7490 },
	{10082, 4194, 6554 },
	{ 9362, 3647, 5825 },
	{ 8192, 3355, 5243 },
	{ 7282, 2893, 4559 }
};

const int FastForward4x4On16x16ITImpl1::ColSelector[16] =
{
	0, 2, 0, 2 ,
	2, 1, 2, 1 ,
	0, 2, 0, 2 ,
	2, 1, 2, 1 
};

/*
---------------------------------------------------------------------------
	Construction.
---------------------------------------------------------------------------
*/
FastForward4x4On16x16ITImpl1::FastForward4x4On16x16ITImpl1()	
{ 
	_mode		= TransformAndQuant; 
	_intra	= 1;
	_q			= 1;
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;

}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place forward Integer Transform.
The 2-D IT is performed on the input and replaces it with the coeffs. A 1-D
transform is performed on the rows first and then the cols.
@param ptr	: Data to transform.
@return			:	none.
*/
#ifdef FF4O16ITI2_UNROLL_LOOPS_AND_INTERLEAVE

void FastForward4x4On16x16ITImpl1::Transform(void* ptr)
{
	short* block = (short *)ptr;

	if(_mode == IForwardTransform::TransformOnly)
	{
		register int s0,s1,s2,s3;
		register int v0,v1,v2,v3;
		register int r0,r1,r2,r3;
		register int u0,u1,u2,u3;

		/// 1-D forward horiz direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	 + block[3]);
		s3 = (int)(block[0]	 - block[3]);
		s1 = (int)(block[1]  + block[2]);
		s2 = (int)(block[1]  - block[2]);
		v0 = (int)(block[4]	 + block[7]);
		v3 = (int)(block[4]	 - block[7]);
		v1 = (int)(block[5]  + block[6]);
		v2 = (int)(block[5]  - block[6]);
		r0 = (int)(block[8]	 + block[11]);
		r3 = (int)(block[8]	 - block[11]);
		r1 = (int)(block[9]  + block[10]);
		r2 = (int)(block[9]  - block[10]);
		u0 = (int)(block[12] + block[15]);
		u3 = (int)(block[12] - block[15]);
		u1 = (int)(block[13] + block[14]);
		u2 = (int)(block[13] - block[14]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(s2 + (s3 << 1));
		block[2]	= (short)(s0 - s1);
		block[3]	= (short)(s3 - (s2 << 1));
		block[4]	= (short)(v0 + v1);
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(v0 - v1);
		block[7]	= (short)(v3 - (v2 << 1));
		block[8]	= (short)(r0 + r1);
		block[9]	= (short)(r2 + (r3 << 1));
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(r3 - (r2 << 1));
		block[12]	= (short)(u0 + u1);
		block[13]	= (short)(u2 + (u3 << 1));
		block[14]	= (short)(u0 - u1);
		block[15]	= (short)(u3 - (u2 << 1));

		/// 1-D forward vert direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	+ block[12]);
		s3 = (int)(block[0]	- block[12]);
		v0 = (int)(block[1]	+ block[13]);
		v3 = (int)(block[1]	- block[13]);
		r0 = (int)(block[2]	+ block[14]);
		r3 = (int)(block[2]	- block[14]);
		u0 = (int)(block[3]	+ block[15]);
		u3 = (int)(block[3]	- block[15]);
		s1 = (int)(block[4] + block[8]);
		s2 = (int)(block[4] - block[8]);
		v1 = (int)(block[5] + block[9]);
		v2 = (int)(block[5] - block[9]);
		r1 = (int)(block[6] + block[10]);
		r2 = (int)(block[6] - block[10]);
		u1 = (int)(block[7] + block[11]);
		u2 = (int)(block[7] - block[11]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(v0 + v1);
		block[2]	= (short)(r0 + r1);
		block[3]	= (short)(u0 + u1);
		block[4]	= (short)(s2 + (s3 << 1));
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(r2 + (r3 << 1));
		block[7]	= (short)(u2 + (u3 << 1));
		block[8]	= (short)(s0 - s1);
		block[9]	= (short)(v0 - v1);
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(u0 - u1);
		block[12]	= (short)(s3 - (s2 << 1));
		block[13]	= (short)(v3 - (v2 << 1));
		block[14]	= (short)(r3 - (r2 << 1));
		block[15]	= (short)(u3 - (u2 << 1));

	}//end if TransformOnly...
	else if(_mode == IForwardTransform::QuantOnly)
	{
		/// Scaling and quantisation are combined.
		const int* pNorm = NormAdjust[_qm];

		/// [0]
		if( block[0] >= 0 )
			block[0] = (short)( (((int)block[0] * pNorm[0]) + _f) >> _scale );
		else
			block[0] = (short)(-( (((-(int)block[0]) * pNorm[0]) + _f) >> _scale ));
		/// [1]
		if( block[1] >= 0 )
			block[1] = (short)( (((int)block[1] * pNorm[2]) + _f) >> _scale );
		else
			block[1] = (short)(-( (((-(int)block[1]) * pNorm[2]) + _f) >> _scale ));
		/// [2]
		if( block[2] >= 0 )
			block[2] = (short)( (((int)block[2] * pNorm[0]) + _f) >> _scale );
		else
			block[2] = (short)(-( (((-(int)block[2]) * pNorm[0]) + _f) >> _scale ));
		/// [3]
		if( block[3] >= 0 )
			block[3] = (short)( (((int)block[3] * pNorm[2]) + _f) >> _scale );
		else
			block[3] = (short)(-( (((-(int)block[3]) * pNorm[2]) + _f) >> _scale ));
		/// [4]
		if( block[4] >= 0 )
			block[4] = (short)( (((int)block[4] * pNorm[2]) + _f) >> _scale );
		else
			block[4] = (short)(-( (((-(int)block[4]) * pNorm[2]) + _f) >> _scale ));
		/// [5]
		if( block[5] >= 0 )
			block[5] = (short)( (((int)block[5] * pNorm[1]) + _f) >> _scale );
		else
			block[5] = (short)(-( (((-(int)block[5]) * pNorm[1]) + _f) >> _scale ));
		/// [6]
		if( block[6] >= 0 )
			block[6] = (short)( (((int)block[6] * pNorm[2]) + _f) >> _scale );
		else
			block[6] = (short)(-( (((-(int)block[6]) * pNorm[2]) + _f) >> _scale ));
		/// [7]
		if( block[7] >= 0 )
			block[7] = (short)( (((int)block[7] * pNorm[1]) + _f) >> _scale );
		else
			block[7] = (short)(-( (((-(int)block[7]) * pNorm[1]) + _f) >> _scale ));
		/// [8]
		if( block[8] >= 0 )
			block[8] = (short)( (((int)block[8] * pNorm[0]) + _f) >> _scale );
		else
			block[8] = (short)(-( (((-(int)block[8]) * pNorm[0]) + _f) >> _scale ));
		/// [9]
		if( block[9] >= 0 )
			block[9] = (short)( (((int)block[9] * pNorm[2]) + _f) >> _scale );
		else
			block[9] = (short)(-( (((-(int)block[9]) * pNorm[2]) + _f) >> _scale ));
		/// [10]
		if( block[10] >= 0 )
			block[10] = (short)( (((int)block[10] * pNorm[0]) + _f) >> _scale );
		else
			block[10] = (short)(-( (((-(int)block[10]) * pNorm[0]) + _f) >> _scale ));
		/// [11]
		if( block[11] >= 0 )
			block[11] = (short)( (((int)block[11] * pNorm[2]) + _f) >> _scale );
		else
			block[11] = (short)(-( (((-(int)block[11]) * pNorm[2]) + _f) >> _scale ));
		/// [12]
		if( block[12] >= 0 )
			block[12] = (short)( (((int)block[12] * pNorm[2]) + _f) >> _scale );
		else
			block[12] = (short)(-( (((-(int)block[12]) * pNorm[2]) + _f) >> _scale ));
		/// [13]
		if( block[13] >= 0 )
			block[13] = (short)( (((int)block[13] * pNorm[1]) + _f) >> _scale );
		else
			block[13] = (short)(-( (((-(int)block[13]) * pNorm[1]) + _f) >> _scale ));
		/// [14]
		if( block[14] >= 0 )
			block[14] = (short)( (((int)block[14] * pNorm[2]) + _f) >> _scale );
		else
			block[14] = (short)(-( (((-(int)block[14]) * pNorm[2]) + _f) >> _scale ));
		/// [15]
		if( block[15] >= 0 )
			block[15] = (short)( (((int)block[15] * pNorm[1]) + _f) >> _scale );
		else
			block[15] = (short)(-( (((-(int)block[15]) * pNorm[1]) + _f) >> _scale ));

	}//end if QuantOnly...
	else ///< if (_mode == IForwardTransform::TransformAndQuant)
	{
		register int s0,s1,s2,s3;
		register int v0,v1,v2,v3;
		register int r0,r1,r2,r3;
		register int u0,u1,u2,u3;

		/// 1-D forward horiz direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	 + block[3]);
		s3 = (int)(block[0]	 - block[3]);
		s1 = (int)(block[1]  + block[2]);
		s2 = (int)(block[1]  - block[2]);
		v0 = (int)(block[4]	 + block[7]);
		v3 = (int)(block[4]	 - block[7]);
		v1 = (int)(block[5]  + block[6]);
		v2 = (int)(block[5]  - block[6]);
		r0 = (int)(block[8]	 + block[11]);
		r3 = (int)(block[8]	 - block[11]);
		r1 = (int)(block[9]  + block[10]);
		r2 = (int)(block[9]  - block[10]);
		u0 = (int)(block[12] + block[15]);
		u3 = (int)(block[12] - block[15]);
		u1 = (int)(block[13] + block[14]);
		u2 = (int)(block[13] - block[14]);

		/// 2nd stage transform.
		block[0]	= (short)(s0 + s1);
		block[1]	= (short)(s2 + (s3 << 1));
		block[2]	= (short)(s0 - s1);
		block[3]	= (short)(s3 - (s2 << 1));
		block[4]	= (short)(v0 + v1);
		block[5]	= (short)(v2 + (v3 << 1));
		block[6]	= (short)(v0 - v1);
		block[7]	= (short)(v3 - (v2 << 1));
		block[8]	= (short)(r0 + r1);
		block[9]	= (short)(r2 + (r3 << 1));
		block[10]	= (short)(r0 - r1);
		block[11]	= (short)(r3 - (r2 << 1));
		block[12]	= (short)(u0 + u1);
		block[13]	= (short)(u2 + (u3 << 1));
		block[14]	= (short)(u0 - u1);
		block[15]	= (short)(u3 - (u2 << 1));

		/// 1-D forward vert direction.

		/// 1-D forward vert direction.

		/// 1st stage transform.
		s0 = (int)(block[0]	+ block[12]);
		s3 = (int)(block[0]	- block[12]);
		v0 = (int)(block[1]	+ block[13]);
		v3 = (int)(block[1]	- block[13]);
		r0 = (int)(block[2]	+ block[14]);
		r3 = (int)(block[2]	- block[14]);
		u0 = (int)(block[3]	+ block[15]);
		u3 = (int)(block[3]	- block[15]);
		s1 = (int)(block[4] + block[8]);
		s2 = (int)(block[4] - block[8]);
		v1 = (int)(block[5] + block[9]);
		v2 = (int)(block[5] - block[9]);
		r1 = (int)(block[6] + block[10]);
		r2 = (int)(block[6] - block[10]);
		u1 = (int)(block[7] + block[11]);
		u2 = (int)(block[7] - block[11]);

		/// 2nd stage transform.

		const int* pNorm = NormAdjust[_qm];

		/// [0]
		if( (s0 + s1) >= 0 )
			block[0] = (short)( (((s0 + s1) * pNorm[0]) + _f) >> _scale );
		else
			block[0] = (short)(-( (((-(s0 + s1)) * pNorm[0]) + _f) >> _scale ));
		/// [1]
		if( (v0 + v1) >= 0 )
			block[1] = (short)( (((v0 + v1) * pNorm[2]) + _f) >> _scale );
		else
			block[1] = (short)(-( (((-(v0 + v1)) * pNorm[2]) + _f) >> _scale ));
		/// [2]
		if( (r0 + r1) >= 0 )
			block[2] = (short)( (((r0 + r1) * pNorm[0]) + _f) >> _scale );
		else
			block[2] = (short)(-( (((-(r0 + r1)) * pNorm[0]) + _f) >> _scale ));
		/// [3]
		if( (u0 + u1) >= 0 )
			block[3] = (short)( (((u0 + u1) * pNorm[2]) + _f) >> _scale );
		else
			block[3] = (short)(-( (((-(u0 + u1)) * pNorm[2]) + _f) >> _scale ));

		/// [4]
		register int x4	= s2 + (s3 << 1);
		if( x4 >= 0 )
			block[4] = (short)( ((x4 * pNorm[2]) + _f) >> _scale );
		else
			block[4] = (short)(-( (((-x4) * pNorm[2]) + _f) >> _scale ));
		/// [5]
		register int x5	= v2 + (v3 << 1);
		if( x5 >= 0 )
			block[5] = (short)( ((x5 * pNorm[1]) + _f) >> _scale );
		else
			block[5] = (short)(-( (((-x5) * pNorm[1]) + _f) >> _scale ));
		/// [6]
		register int x6	= r2 + (r3 << 1);
		if( x6 >= 0 )
			block[6] = (short)( ((x6 * pNorm[2]) + _f) >> _scale );
		else
			block[6] = (short)(-( (((-x6) * pNorm[2]) + _f) >> _scale ));
		/// [7]
		register int x7	= u2 + (u3 << 1);
		if( x7 >= 0 )
			block[7] = (short)( ((x7 * pNorm[1]) + _f) >> _scale );
		else
			block[7] = (short)(-( (((-x7) * pNorm[1]) + _f) >> _scale ));

		/// [8]
		if( (s0 - s1) >= 0 )
			block[8] = (short)( (((s0 - s1) * pNorm[0]) + _f) >> _scale );
		else
			block[8] = (short)(-( (((-(s0 - s1)) * pNorm[0]) + _f) >> _scale ));
		/// [9]
		if( (v0 - v1) >= 0 )
			block[9] = (short)( (((v0 - v1) * pNorm[2]) + _f) >> _scale );
		else
			block[9] = (short)(-( (((-(v0 - v1)) * pNorm[2]) + _f) >> _scale ));
		/// [10]
		if( (r0 - r1) >= 0 )
			block[10] = (short)( (((r0 - r1) * pNorm[0]) + _f) >> _scale );
		else
			block[10] = (short)(-( (((-(r0 - r1)) * pNorm[0]) + _f) >> _scale ));
		/// [11]
		if( (u0 - u1) >= 0 )
			block[11] = (short)( (((u0 - u1) * pNorm[2]) + _f) >> _scale );
		else
			block[11] = (short)(-( (((-(u0 - u1)) * pNorm[2]) + _f) >> _scale ));

		/// [12]
		register int x12	= s3 - (s2 << 1);
		if( x12 >= 0 )
			block[12] = (short)( ((x12 * pNorm[2]) + _f) >> _scale );
		else
			block[12] = (short)(-( (((-x12) * pNorm[2]) + _f) >> _scale ));
		/// [13]
		register int x13	= v3 - (v2 << 1);
		if( x13 >= 0 )
			block[13] = (short)( ((x13 * pNorm[1]) + _f) >> _scale );
		else
			block[13] = (short)(-( (((-x13) * pNorm[1]) + _f) >> _scale ));
		/// [14]
		register int x14	= r3 - (r2 << 1);
		if( x14 >= 0 )
			block[14] = (short)( ((x14 * pNorm[2]) + _f) >> _scale );
		else
			block[14] = (short)(-( (((-x14) * pNorm[2]) + _f) >> _scale ));
		/// [15]
		register int x15	= u3 - (u2 << 1);
		if( x15 >= 0 )
			block[15] = (short)( ((x15 * pNorm[1]) + _f) >> _scale );
		else
			block[15] = (short)(-( (((-x15) * pNorm[1]) + _f) >> _scale ));

	}//end else...

}//end Transform.

#else ///< !FF4O16ITI2_UNROLL_LOOPS_AND_INTERLEAVE

void FastForward4x4On16x16ITImpl1::Transform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	if(_mode == IForwardTransform::TransformOnly)
	{
		/// 1-D forward horiz direction.
		for(j = 0; j < 256; j += 16)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			int s4 = (int)(block[j+4]	+ block[j+7]);
			int s7 = (int)(block[j+4]	- block[j+7]);
			int s5 = (int)(block[j+5] + block[j+6]);
			int s6 = (int)(block[j+5] - block[j+6]);

			int s8  = (int)(block[j+8] + block[j+11]);
			int s11 = (int)(block[j+8] - block[j+11]);
			int s9  = (int)(block[j+9] + block[j+10]);
			int s10 = (int)(block[j+9] - block[j+10]);

			int s12 = (int)(block[j+12] + block[j+15]);
			int s15 = (int)(block[j+12] - block[j+15]);
			int s13 = (int)(block[j+13] + block[j+14]);
			int s14 = (int)(block[j+13] - block[j+14]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+1]	= (short)(s2 + (s3 << 1));
			block[j+2]	= (short)(s0 - s1);
			block[j+3]	= (short)(s3 - (s2 << 1));

			block[j+4]	= (short)(s4 + s5);
			block[j+5]	= (short)(s6 + (s7 << 1));
			block[j+6]	= (short)(s4 - s5);
			block[j+7]	= (short)(s7 - (s6 << 1));

			block[j+8]	= (short)(s8 + s9);
			block[j+9]	= (short)(s10 + (s11 << 1));
			block[j+10]	= (short)(s8 - s9);
			block[j+11]	= (short)(s11 - (s10 << 1));

			block[j+12]	= (short)(s12 + s13);
			block[j+13]	= (short)(s14 + (s15 << 1));
			block[j+14]	= (short)(s12 - s13);
			block[j+15]	= (short)(s15 - (s14 << 1));

		}//end for j...

		/// 1-D forward vert direction.
		for(j = 0; j < 16; j++)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+48]);
			int s3 = (int)(block[j]		- block[j+48]);
			int s1 = (int)(block[j+16] + block[j+32]);
			int s2 = (int)(block[j+16] - block[j+32]);

			int s4 = (int)block[j+64]	+ (int)block[j+112];
			int s7 = (int)block[j+64]	- (int)block[j+112];
			int s5 = (int)block[j+80]	+ (int)block[j+96];
			int s6 = (int)block[j+80]	- (int)block[j+96];

			int s8  = (int)block[j+128]	+ (int)block[j+176];
			int s11 = (int)block[j+128]	- (int)block[j+176];
			int s9  = (int)block[j+144]	+ (int)block[j+160];
			int s10 = (int)block[j+144]	- (int)block[j+160];

			int s12 = (int)block[j+192]	+ (int)block[j+240];
			int s15 = (int)block[j+192]	- (int)block[j+240];
			int s13 = (int)block[j+208]	+ (int)block[j+224];
			int s14 = (int)block[j+208]	- (int)block[j+224];

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+16]	= (short)(s2 + (s3 << 1));
			block[j+32]	= (short)(s0 - s1);
			block[j+48]	= (short)(s3 - (s2 << 1));

			block[j+64]  = (short)(s4 + s5);
			block[j+80]  = (short)(s6 + (s7 << 1));
			block[j+96]  = (short)(s4 - s5);
			block[j+112] = (short)(s7 - (s6 << 1));

			block[j+128]  = (short)(s8  + s9);
			block[j+144]  = (short)(s10 + (s11 << 1));
			block[j+160] = (short)(s8  - s9);
			block[j+176] = (short)(s11 - (s10 << 1));

 			block[j+192] = (short)(s12 + s13);
			block[j+208] = (short)(s14 + (s15 << 1));
			block[j+224] = (short)(s12 - s13);
			block[j+240] = (short)(s15 - (s14 << 1));
		}//end for j...

	}//end if TransformOnly...
	else if(_mode == IForwardTransform::QuantOnly)
	{
		/// Scaling and quantisation are combined.
		const int* pNorm = NormAdjust[_qm];
		for(int i = 0; i < 16; i++)
    {
      int k = i % 4;
 		  for(j = 0; j < 16; j++)
		  {
        int l = j % 4;
			  if( block[i*16 + j] >= 0 )
				  block[i*16 + j] = (short)( (((int)block[i*16 + j] * pNorm[ColSelector[k*4 + l]]) + _f) >> _scale );
			  else
				  block[i*16 + j] = (short)(-( (((-(int)block[i*16 + j]) * pNorm[ColSelector[k*4 + l]]) + _f) >> _scale ));
		  }//end for j...
    }//end for i...
	}//end if QuantOnly...
	else ///< if (_mode == IForwardTransform::TransformAndQuant)
	{
		const int* pNorm = NormAdjust[_qm];

		/// 1-D forward horiz direction.
		for(j = 0; j < 256; j += 16)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			int s4 = (int)(block[j+4]	+ block[j+7]);
			int s7 = (int)(block[j+4]	- block[j+7]);
			int s5 = (int)(block[j+5] + block[j+6]);
			int s6 = (int)(block[j+5] - block[j+6]);

			int s8  = (int)(block[j+8] + block[j+11]);
			int s11 = (int)(block[j+8] - block[j+11]);
			int s9  = (int)(block[j+9] + block[j+10]);
			int s10 = (int)(block[j+9] - block[j+10]);

			int s12 = (int)(block[j+12] + block[j+15]);
			int s15 = (int)(block[j+12] - block[j+15]);
			int s13 = (int)(block[j+13] + block[j+14]);
			int s14 = (int)(block[j+13] - block[j+14]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+1]	= (short)(s2 + (s3 << 1));
			block[j+2]	= (short)(s0 - s1);
			block[j+3]	= (short)(s3 - (s2 << 1));

			block[j+4]	= (short)(s4 + s5);
			block[j+5]	= (short)(s6 + (s7 << 1));
			block[j+6]	= (short)(s4 - s5);
			block[j+7]	= (short)(s7 - (s6 << 1));

			block[j+8]	= (short)(s8 + s9);
			block[j+9]	= (short)(s10 + (s11 << 1));
			block[j+10]	= (short)(s8 - s9);
			block[j+11]	= (short)(s11 - (s10 << 1));

			block[j+12]	= (short)(s12 + s13);
			block[j+13]	= (short)(s14 + (s15 << 1));
			block[j+14]	= (short)(s12 - s13);
			block[j+15]	= (short)(s15 - (s14 << 1));

		}//end for j...

		/// 1-D forward vert direction.
		for(j = 0; j < 16; j++)
		{
			/// 1st stage transform.
			int s0 = (int)block[j]		+ (int)block[j+48];
			int s3 = (int)block[j]		- (int)block[j+48];
			int s1 = (int)block[j+16]	+ (int)block[j+32];
			int s2 = (int)block[j+16]	- (int)block[j+32];

			int s4 = (int)block[j+64]	+ (int)block[j+112];
			int s7 = (int)block[j+64]	- (int)block[j+112];
			int s5 = (int)block[j+80]	+ (int)block[j+96];
			int s6 = (int)block[j+80]	- (int)block[j+96];

			int s8  = (int)block[j+128]	+ (int)block[j+176];
			int s11 = (int)block[j+128]	- (int)block[j+176];
			int s9  = (int)block[j+144]	+ (int)block[j+160];
			int s10 = (int)block[j+144]	- (int)block[j+160];

			int s12 = (int)block[j+192]	+ (int)block[j+240];
			int s15 = (int)block[j+192]	- (int)block[j+240];
			int s13 = (int)block[j+208]	+ (int)block[j+224];
			int s14 = (int)block[j+208]	- (int)block[j+224];

			/// 2nd stage transform with scaling and quantisation.
			int x0 = s0 + s1;
			int x1 = s2 + (s3 << 1);
			int x2 = s0 - s1;
			int x3 = s3 - (s2 << 1);

			int x4 = s4 + s5;
			int x5 = s6 + (s7 << 1);
			int x6 = s4 - s5;
			int x7 = s7 - (s6 << 1);

			int x8  = s8  + s9;
			int x9  = s10 + (s11 << 1);
			int x10 = s8  - s9;
			int x11 = s11 - (s10 << 1);

 			int x12 = s12 + s13;
			int x13 = s14 + (s15 << 1);
			int x14 = s12 - s13;
			int x15 = s15 - (s14 << 1);

     int k = j % 4;

     const int n0 = pNorm[ColSelector[k]];
			if(x0 < 0)
				block[j] = (short)(-( (((-x0) * n0) + _f) >> _scale ));
			else
				block[j] = (short)( ((x0 * n0) + _f) >> _scale );
			if(x4 < 0)
				block[j+64] = (short)(-( (((-x4) * n0) + _f) >> _scale ));
			else
				block[j+64] = (short)( ((x4 * n0) + _f) >> _scale );
			if(x8 < 0)
				block[j+128] = (short)(-( (((-x8) * n0) + _f) >> _scale ));
			else
				block[j+128] = (short)( ((x8 * n0) + _f) >> _scale );
			if(x12 < 0)
				block[j+192] = (short)(-( (((-x12) * n0) + _f) >> _scale ));
			else
				block[j+192] = (short)( ((x12 * n0) + _f) >> _scale );

      const int n1 = pNorm[ColSelector[k+4]];
			if(x1 < 0)
				block[j+16] = (short)(-( (((-x1) * n1) + _f) >> _scale ));
			else
				block[j+16] = (short)( ((x1 * n1) + _f) >> _scale );
			if(x5 < 0)
				block[j+80] = (short)(-( (((-x5) * n1) + _f) >> _scale ));
			else
				block[j+80] = (short)( ((x5 * n1) + _f) >> _scale );
			if(x9 < 0)
				block[j+144] = (short)(-( (((-x9) * n1) + _f) >> _scale ));
			else
				block[j+144] = (short)( ((x9 * n1) + _f) >> _scale );
			if(x13 < 0)
				block[j+208] = (short)(-( (((-x13) * n1) + _f) >> _scale ));
			else
				block[j+208] = (short)( ((x13 * n1) + _f) >> _scale );

      const int n2 = pNorm[ColSelector[k+8]];
			if(x2 < 0)
				block[j+32] = (short)(-( (((-x2) * n2) + _f) >> _scale ));
			else
				block[j+32] = (short)( ((x2 * n2) + _f) >> _scale );
			if(x6 < 0)
				block[j+96] = (short)(-( (((-x6) * n2) + _f) >> _scale ));
			else
				block[j+96] = (short)( ((x6 * n2) + _f) >> _scale );
			if(x10 < 0)
				block[j+160] = (short)(-( (((-x10) * n2) + _f) >> _scale ));
			else
				block[j+160] = (short)( ((x10 * n2) + _f) >> _scale );
			if(x14 < 0)
				block[j+224] = (short)(-( (((-x14) * n2) + _f) >> _scale ));
			else
				block[j+224] = (short)( ((x14 * n2) + _f) >> _scale );

      const int n3 = pNorm[ColSelector[k+12]];
			if(x3 < 0)
				block[j+48] = (short)(-( (((-x3) * n3) + _f) >> _scale ));
			else
				block[j+48] = (short)( ((x3 * n3) + _f) >> _scale );
			if(x7 < 0)
				block[j+112] = (short)(-( (((-x7) * n3) + _f) >> _scale ));
			else
				block[j+112] = (short)( ((x7 * n3) + _f) >> _scale );
			if(x11 < 0)
				block[j+176] = (short)(-( (((-x11) * n3) + _f) >> _scale ));
			else
				block[j+176] = (short)( ((x11 * n3) + _f) >> _scale );
			if(x15 < 0)
				block[j+240] = (short)(-( (((-x15) * n3) + _f) >> _scale ));
			else
				block[j+240] = (short)( ((x15 * n3) + _f) >> _scale );
		}//end for j...
	}//end else...

}//end Transform.

#endif 

/** Transfer forward IT.
The IT is performed on the input and the coeffs are written to 
the output.
@param pIn		: Input data.
@param pCoeff	: Output coeffs.
@return				:	none.
*/
void FastForward4x4On16x16ITImpl1::Transform(void* pIn, void* pCoeff)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pCoeff, pIn, sizeof(short) * 256);
	Transform(pCoeff);
}//end Transform.

/** Set and get parameters for the implementation.
An Intra and Inter parameter and quantisation parameter are the only 
requirement for this implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastForward4x4On16x16ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_q = paramVal;
          SetNewQP();
				}//end if q...
			}//end case QUANT_ID...
			break;
		case INTRA_FLAG_ID:
			_intra = paramVal;
      SetNewQP();
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastForward4x4On16x16ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		case INTRA_FLAG_ID:
			ret = _intra;
			break;
		default :
			ret = _intra;	///< Intra flag is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.

/** Set internal quant members based on _q.
@return: none.
*/
void FastForward4x4On16x16ITImpl1::SetNewQP(void)
{
	_qm			= _q % 6;
	_qe			= _q/6;
	if(_intra)
		_f = (1 << (15+_qe))/3;
	else
		_f = (1 << (15+_qe))/6;
	_scale	= 15+_qe;
}//end SetNewQP.
========== END FILE: CodecUtils/FastForward4x4On16x16ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastForward4x4On16x16ITImpl1.h ==========
Bundle entry: 39
Original bytes: 5458
Original SHA-256: ef93878c6681cb62c79b64f93d3a26024ff7782ffd59db9cd14b9c27c446d04c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForward4x4On16x16ITImpl1

TAG						: FF4O16ITI2

FILE NAME			: FastForward4x4On16x16ITImpl1.h

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								transform defined by the H.264 standard on the 16x16
                macroblock input. It implements the IForwardTransform 
                interface. The scaling	is part of the quantisation process.

COPYRIGHT			: (c)CSIR 2007-2011 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================================
*/
#ifndef _FASTFORWARD4X4ON16X16ITIMPL1_H
#define _FASTFORWARD4X4ON16X16ITIMPL1_H

#pragma once

#include "IForwardTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastForward4x4On16x16ITImpl1 : public IForwardTransform
{
	public:
		FastForward4x4On16x16ITImpl1();
		virtual ~FastForward4x4On16x16ITImpl1()	{ }

	// Interface implementation.
	public:
		/** In-place forward IT.
		The IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void Transform(void* ptr);

		/** Transfer forward IT.
		The IT is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void Transform(void* pIn, void* pCoeff);

		/** Set scaling array.
		Each coefficient may be scaled after transforming and therefore 
		requires setting up. Only the default scaling is used and 
		therefore this method is not implemented.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale) { }
		virtual void* GetScale(void) { return(NULL); }

		/** Set/Get the mode of operation.
		The modes for this implementation set the combinations of 
		including or excluding the transform with or without quantisation.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		An Intra and Inter parameter and the quantisation parameter are the 
		only requirement for this	implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

    /** Quantise a single value in a block.
    Implement quantising a value in a specified position of the coeffs at a
    specified QP value.
    @param val  : Value to quantise.
    @param pos  : Postion of value in 1-D array of 2-D data.
    @param qp   : Quant param to use.
    @return     : Result of quntisation.
    */
    virtual int QuantiseValue(short val, int pos, int qp) { return(0); }

    /// Internal methods
  private:
    /** Set internal quant members based on _q.
    @return: none.
    */
    void SetNewQP(void);

		/// Constants.
	protected:
		static const int NormAdjust[6][3];
		static const int ColSelector[16];

	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.
		int _intra;	///< 0 = Inter, 1 = Intra.

		/// Hold these members that will only change when q changes.
		int	_q;				///< Current quantisation parameter.
		int	_qm;			///< _q % 6.
		int _qe;			///< _q / 6.
		int _f;				///< Rounding shift = (1 << (15+_qe))/6.
		int _scale;		///< Scaling shift = 15+_qe;

};// end class FastForward4x4On16x16ITImpl1.

#endif	//_FASTFORWARD4X4ON16X16ITIMPL1_H
========== END FILE: CodecUtils/FastForward4x4On16x16ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastForwardDC2x2ITImpl1.cpp ==========
Bundle entry: 40
Original bytes: 7011
Original SHA-256: e34180f9c57f597a08e3f7175a0f165541b1af3e4ab8e1aba8d2f62d552c4723
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForwardDC2x2ITImpl1

TAG						: FFDC2ITI1

FILE NAME			: FastForwardDC2x2ITImpl1.cpp

DESCRIPTION		: A class to implement a fast forward 2x2 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IForwardTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

======================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastForwardDC2x2ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/

const int FastForwardDC2x2ITImpl1::NormAdjust[6] =
{
	13107, 
	11916, 
	10082, 
	 9362, 
	 8192, 
	 7282
};

/*
---------------------------------------------------------------------------
	Construction and Destruction.
---------------------------------------------------------------------------
*/
FastForwardDC2x2ITImpl1::FastForwardDC2x2ITImpl1()
{ 
	_mode = 0; 
	_q			= 1;
	_qm			= _q % 6;
	_qe			= _q/6;
//	_f			= (1 << (14+_qe))/6;
//	_scale	= 14+_qe;
	_f			= 2 * ((1 << (15+_qe))/3);
	_scale	= 16 + _qe;
}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place forward Integer Transform.
The 2-D IT is performed on the input and replaces it with the coeffs. A 1-D
transform is performed on the rows first and then the cols.
@param ptr	: Data to transform.
@return			:	none.
*/
void FastForwardDC2x2ITImpl1::Transform(void* ptr)
{
	short* block = (short *)ptr;

	/// Only do IT modes = 0 & 1.
	if(_mode != QuantOnly)	///< 2 = Q only.
	{
		/// 1st stage transform.
		int s0 = (int)(block[0]	+ block[1]);
		int s2 = (int)(block[0] - block[1]);
		int s1 = (int)(block[2] + block[3]);
		int s3 = (int)(block[2]	- block[3]);

		if(_mode == TransformAndQuant)	///< 0 = IT+Q.
		{
			/// 2nd stage transform with scaling and quantisation.
			int x0 = s0 + s1;
			if(x0 < 0)
				block[0] = (short)(-( (((-x0) * NormAdjust[_qm]) + _f) >> _scale ));
			else
				block[0] = (short)( ((x0 * NormAdjust[_qm]) + _f) >> _scale );

			int x2 = s0 - s1;
			if(x2 < 0)
				block[2] = (short)(-( (((-x2) * NormAdjust[_qm]) + _f) >> _scale ));
			else
				block[2] = (short)( ((x2 * NormAdjust[_qm]) + _f) >> _scale );

			int x1 = s2 + s3;
			if(x1 < 0)
				block[1] = (short)(-( (((-x1) * NormAdjust[_qm]) + _f) >> _scale ));
			else
				block[1] = (short)( ((x1 * NormAdjust[_qm]) + _f) >> _scale );

			int x3 = s2 - s3;
			if(x3 < 0)
				block[3] = (short)(-( (((-x3) * NormAdjust[_qm]) + _f) >> _scale ));
			else
				block[3] = (short)( ((x3 * NormAdjust[_qm]) + _f) >> _scale );
		}//end if _mode...
		else	///< mode = 1 i.e. IT only.
		{
			/// 2nd stage transform.
			block[0]	= (short)(s0 + s1);
			block[2]	= (short)(s0 - s1);
			block[1]	= (short)(s2 + s3);
			block[3]	= (short)(s2 - s3);
		}//end else...
	}//end if _mode != 2...
	else ///< mode = 2 i.e. Q only.
	{
		/// Scaling and quantisation are combined.
		int i,j;
		for(i = 0; i < 2; i++)
			for(j = 0; j < 2; j++)
			{
				int x = (int)block[i*2 + j];
				if( x < 0 )
					block[i*2 + j] = (short)(-( (((-x) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[i*2 + j] = (short)( ((x * NormAdjust[_qm]) + _f) >> _scale );
			}//end for i & j...
	}//end else...

}//end Transform.

/** Transfer forward IT.
The IT is performed on the input and the coeffs are written to 
the output.
@param pIn		: Input data.
@param pCoeff	: Output coeffs.
@return				:	none.
*/
void FastForwardDC2x2ITImpl1::Transform(void* pIn, void* pCoeff)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pCoeff, pIn, sizeof(short) * 4);
	Transform(pCoeff);
}//end Transform.

/** Set and get parameters for the implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastForwardDC2x2ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm			= paramVal % 6;
					_qe			= paramVal/6;
//					_f			= (1 << (14+_qe))/6;
//					_scale	= 14+_qe;
	        _f			= 2 * ((1 << (15+_qe))/3);
	        _scale	= 16 + _qe;
					_q			= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastForwardDC2x2ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.

========== END FILE: CodecUtils/FastForwardDC2x2ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastForwardDC2x2ITImpl1.h ==========
Bundle entry: 41
Original bytes: 5041
Original SHA-256: fcf9112279d21919eb53faa938f42f8cc3fec1d4e4d2b56f8e7906955ea4f4b0
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForwardDC2x2ITImpl1

TAG						: FFDC2ITI1

FILE NAME			: FastForwardDC2x2ITImpl1.h

DESCRIPTION		: A class to implement a fast forward 2x2 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IForwardTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _FASTFORWARDDC2X2ITIMPL1_H
#define _FASTFORWARDDC2X2ITIMPL1_H

#pragma once

#include "IForwardTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastForwardDC2x2ITImpl1 : public IForwardTransform
{
	public:
		FastForwardDC2x2ITImpl1();
		virtual ~FastForwardDC2x2ITImpl1()	{ }

	/// Interface implementation.
	public:
		/** In-place forward IT.
		The IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void Transform(void* ptr);

		/** Transfer forward IT.
		The IT is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void Transform(void* pIn, void* pCoeff);

		/** Set scaling array.
		Each coefficient may be scaled after transforming and therefore 
		requires setting up. Only the default scaling is used and 
		therefore this method is not implemented.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale) { }
		virtual void* GetScale(void) { return(NULL); }

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

    /** Quantise a single value in a block.
    Implement quantising a value in a specified position of the coeffs at a
    specified QP value.
    @param val  : Value to quantise.
    @param pos  : Postion of value in 1-D array of 2-D data.
    @param qp   : Quant param to use.
    @return     : Result of quntisation.
    */
    virtual int QuantiseValue(short val, int pos, int qp) { return(0); }

		/// Constants.
	protected:
		static const int NormAdjust[6];

	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		/// Hold these members that will only change when q changes.
		int	_q;				///< Current quantisation parameter.
		int	_qm;			///< _q % 6.
		int _qe;			///< _q / 6.
		int _f;				///< Rounding shift = (1 << (16+_qe))/6.
		int _scale;		///< Scaling shift = 16+_qe;

};// end class FastForwardDC2x2ITImpl1.

#endif	//_FASTFORWARDDC2X2ITIMPL1_H
========== END FILE: CodecUtils/FastForwardDC2x2ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastForwardDC4x4ITImpl1.cpp ==========
Bundle entry: 42
Original bytes: 8846
Original SHA-256: 8cb0d088d2d4006fa43904407419506cbf27ee8705f3833ba589f7fdc83fe6c1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForwardDC4x4ITImpl1

TAG						: FFDC4ITI1

FILE NAME			: FastForwardDC4x4ITImpl1.cpp

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IForwardTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include <math.h>
#include "FastForwardDC4x4ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/

const int FastForwardDC4x4ITImpl1::NormAdjust[6] =
{
	13107, 
	11916, 
	10082, 
	 9362, 
	 8192, 
	 7282
};

/*
---------------------------------------------------------------------------
	Construction and Destruction.
---------------------------------------------------------------------------
*/
FastForwardDC4x4ITImpl1::FastForwardDC4x4ITImpl1()
{ 
	_mode		= TransformAndQuant; 
	_q			= 1;
	_qm			= _q % 6;
	_qe			= _q/6;
//	_f			= (1 << (15+_qe))/6;
//	_scale	= 15+_qe;
	_f			= 2 * ((1 << (15+_qe))/3);
	_scale	= 16 + _qe;
}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place forward Integer Transform.
The 2-D IT is performed on the input and replaces it with the coeffs. A 1-D
transform is performed on the rows first and then the cols.
@param ptr	: Data to transform.
@return			:	none.
*/
void FastForwardDC4x4ITImpl1::Transform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	/// Only do IT modes = 0 & 1.
	if(_mode != QuantOnly)	///< 2 = Q only.
	{
		/// 1-D forward horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage transform.
			int s0 = (int)(block[j]		+ block[j+3]);
			int s3 = (int)(block[j]		- block[j+3]);
			int s1 = (int)(block[j+1] + block[j+2]);
			int s2 = (int)(block[j+1] - block[j+2]);

			/// 2nd stage transform.
			block[j]		= (short)(s0 + s1);
			block[j+2]	= (short)(s0 - s1);
			block[j+1]	= (short)(s2 + s3);
			block[j+3]	= (short)(s3 - s2);
		}//end for j...

		/// 1-D forward vert direction.

		if(_mode == TransformAndQuant)	///< 0 = IT+Q.
		{
			for(j = 0; j < 4; j++)
			{
				/// 1st stage transform.
				int s0 = (int)block[j]		+ (int)block[j+12];
				int s3 = (int)block[j]		- (int)block[j+12];
				int s1 = (int)block[j+4]	+ (int)block[j+8];
				int s2 = (int)block[j+4]	- (int)block[j+8];

				/// 2nd stage transform with scaling and quantisation.
				int x0 = (s0 + s1) >> 1;
				if(x0 < 0)
					block[j] = (short)(-( (((-x0) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[j] = (short)( ((x0 * NormAdjust[_qm]) + _f) >> _scale );

				int x2 = (s0 - s1) >> 1;
				if(x2 < 0)
					block[j+8] = (short)(-( (((-x2) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[j+8] = (short)( ((x2 * NormAdjust[_qm]) + _f) >> _scale );

				int x1 = (s2 + s3) >> 1;
				if(x1 < 0)
					block[j+4] = (short)(-( (((-x1) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[j+4] = (short)( ((x1 * NormAdjust[_qm]) + _f) >> _scale );

				int x3 = (s3 - s2) >> 1;
				if(x3 < 0)
					block[j+12] = (short)(-( (((-x3) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[j+12] = (short)( ((x3 * NormAdjust[_qm]) + _f) >> _scale );
			}//end for j...
		}//end if _mode...
		else	///< mode = 1 i.e. IT only.
		{
			for(j = 0; j < 4; j++)
			{
				/// 1st stage transform.
				int s0 = (int)(block[j]		+ block[j+12]);
				int s3 = (int)(block[j]		- block[j+12]);
				int s1 = (int)(block[j+4] + block[j+8]);
				int s2 = (int)(block[j+4] - block[j+8]);

				/// 2nd stage transform.
				block[j]		= (short)((s0 + s1) >> 1);
				block[j+8]	= (short)((s0 - s1) >> 1);
				block[j+4]	= (short)((s2 + s3) >> 1);
				block[j+12]	= (short)((s3 - s2) >> 1);
			}//end for j...
		}//end else...
	}//end if _mode != 2...
	else ///< mode = 2 i.e. Q only.
	{
		/// Scaling and quantisation are combined.
		int i;
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int x = (int)block[i*4 + j];
				if( x < 0 )
					block[i*4 + j] = (short)(-( (((-x) * NormAdjust[_qm]) + _f) >> _scale ));
				else
					block[i*4 + j] = (short)( ((x * NormAdjust[_qm]) + _f) >> _scale );
			}//end for i & j...
	}//end else...

}//end Transform.

/** Transfer forward IT.
The IT is performed on the input and the coeffs are written to 
the output.
@param pIn		: Input data.
@param pCoeff	: Output coeffs.
@return				:	none.
*/
void FastForwardDC4x4ITImpl1::Transform(void* pIn, void* pCoeff)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pCoeff, pIn, sizeof(short) * 16);
	Transform(pCoeff);
}//end Transform.

/** Set and get parameters for the implementation.
An quantisation parameter and quantisation parameter are the only 
requirement for this implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastForwardDC4x4ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm			= paramVal % 6;
					_qe			= paramVal/6;
//					_f			= (1 << (15+_qe))/6;
//					_scale	= 15+_qe;
        	_f			= 2 * ((1 << (15+_qe))/3);
	        _scale	= 16 + _qe;
					_q			= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastForwardDC4x4ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.

/** Quantise a single value in a block.
Implement quantising a value in a specified position of the coeffs at a
specified QP value.
@param val  : Value to quantise.
@param pos  : Postion of value in 1-D array of 2-D data.
@param qp   : Quant param to use.
@return     : Result of quantisation.
*/
int FastForwardDC4x4ITImpl1::QuantiseValue(short val, int pos, int qp)
{
  _q = qp;
	_qm			= qp % 6;
	_qe			= qp/6;
  _f			= 2 * ((1 << (15+_qe))/3);
	_scale	= 16 + _qe;

  short quantVal = 0;
	if( val < 0 )
		quantVal = (short)(-( (((-val) * NormAdjust[_qm]) + _f) >> _scale ));
	else
		quantVal = (short)( ((val * NormAdjust[_qm]) + _f) >> _scale );

  return((int)quantVal);
}//end QuantiseValue. 


========== END FILE: CodecUtils/FastForwardDC4x4ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastForwardDC4x4ITImpl1.h ==========
Bundle entry: 43
Original bytes: 5065
Original SHA-256: 42066bca24bb71f9569653c78e80486dec0637544c4e18b1deb3224808b9c99d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastForwardDC4x4ITImpl1

TAG						: FFDC4ITI1

FILE NAME			: FastForwardDC4x4ITImpl1.h

DESCRIPTION		: A class to implement a fast forward 4x4 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IForwardTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _FASTFORWARDDC4X4ITIMPL1_H
#define _FASTFORWARDDC4X4ITIMPL1_H

#pragma once

#include "IForwardTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastForwardDC4x4ITImpl1 : public IForwardTransform
{
	public:
		FastForwardDC4x4ITImpl1();
		virtual ~FastForwardDC4x4ITImpl1()	{ }

	// Interface implementation.
	public:
		/** In-place forward IT.
		The IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void Transform(void* ptr);

		/** Transfer forward IT.
		The IT is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void Transform(void* pIn, void* pCoeff);

		/** Set scaling array.
		Each coefficient may be scaled after transforming and therefore 
		requires setting up. Only the default scaling is used and 
		therefore this method is not implemented.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale) { }
		virtual void* GetScale(void) { return(NULL); }

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		Undefined for this implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

    /** Quantise a single value in a block.
    Implement quantising a value in a specified position of the coeffs at a
    specified QP value.
    @param val  : Value to quantise.
    @param pos  : Postion of value in 1-D array of 2-D data.
    @param qp   : Quant param to use.
    @return     : Result of quantisation.
    */
    virtual int QuantiseValue(short val, int pos, int qp);

		/// Constants.
	protected:
		static const int NormAdjust[6];

	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		/// Hold these members that will only change when q changes.
		int	_q;				///< Current quantisation parameter.
		int	_qm;			///< _q % 6.
		int _qe;			///< _q / 6.
		int _f;				///< Rounding shift = (1 << (16+_qe))/6.
		int _scale;		///< Scaling shift = 16+_qe;

};// end class FastForwardDC4x4ITImpl1.

#endif	//_FASTFORWARDDC4X4ITIMPL1_H
========== END FILE: CodecUtils/FastForwardDC4x4ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastInverse4x4ITImpl1.cpp ==========
Bundle entry: 44
Original bytes: 9391
Original SHA-256: ac1f311a2e09741a02ee5f8f8c56230d5bd93597e11136931e176334c8aa5883
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverse4x4ITImpl1

TAG						: FII4TI1

FILE NAME			: FastInverse4x4ITImpl1.cpp

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								transform defined by the H.264 standard on the input. 
								It implements the IInverseDct interface. The pre-scaling
								is part of the inverse quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastInverse4x4ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastInverse4x4ITImpl1::NormAdjust[6][3] =
{
	{10, 16, 13 },
	{11, 18, 14 },
	{13, 20, 16 },
	{14, 23, 18 },
	{16, 25, 20 },
	{18, 29, 23 }
};

const int FastInverse4x4ITImpl1::ColSelector[16] =
{
	0, 2, 0, 2 ,
	2, 1, 2, 1 ,
	0, 2, 0, 2 ,
	2, 1, 2, 1 
};

/*
--------------------------------------------------------------------------
	Construction.
--------------------------------------------------------------------------
*/
FastInverse4x4ITImpl1::FastInverse4x4ITImpl1(void)
{
	int i,j,qm;

	for(i = 0; i < 16; i++)
		_weightScale[i] = 16;	///< For baseline Flat_4x4_16 is default.

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm][ColSelector[pos]] * _weightScale[pos];
			}//end for qm & i & j...

	_mode				= TransformAndQuant;
	_q					= 1;
	_qm					= _q % 6;
	_qe					= _q/6;
	_f					= 1 << (3-_qe);
	_leftScale	= _qe-4;
	_rightScale	= 4-_qe;

}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place inverse Integer Transform.
The 2-D inverse IT is performed on the input coeffs and replaces them. A 1-D
inverse transform is performed on the rows first and then the cols. 
@param ptr	: Data to transform.
@return			:	none.
*/
void FastInverse4x4ITImpl1::InverseTransform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	if(_mode == QuantOnly)	///< 2 = Q only.
	{
		/// Pre-scaling and quantisation are combined.
		int i;
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int x = (int)block[i*4 + j] * _levelScale[_qm][i*4 +j];
				if(_q < 24)
					block[i*4 + j] = (short)( (x + _f) >> _rightScale );
				else
					block[i*4 + j] = (short)( x << _leftScale );
			}//end for i & j...
	}//end if _mode == 2...
	else if(_mode == TransformAndQuant)	///< 0 = IT&Q.
	{
		/// 1-D inverse IT in horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage with pre-scaling and quantisation.
			int x0 = (int)block[j]		* _levelScale[_qm][j];
			int x1 = (int)block[j+1]	* _levelScale[_qm][j+1];
			int x2 = (int)block[j+2]	* _levelScale[_qm][j+2];
			int x3 = (int)block[j+3]	* _levelScale[_qm][j+3];
			if(_q < 24)
			{
				x0 = (x0 + _f) >> _rightScale;
				x1 = (x1 + _f) >> _rightScale;
				x2 = (x2 + _f) >> _rightScale;
				x3 = (x3 + _f) >> _rightScale;
			}//end if _q...
			else
			{
				x0 = x0 << _leftScale;
				x1 = x1 << _leftScale;
				x2 = x2 << _leftScale;
				x3 = x3 << _leftScale;
			}//end else...

			int s0 = x0					+ x2;
			int s1 = x0					- x2;
			int s2 = (x1 >> 1)	- x3;
			int s3 = x1					+ (x3 >> 1);

			/// 2nd stage.
			block[j]		= (short)(s0 + s3);
			block[3+j]	= (short)(s0 - s3);
			block[1+j]	= (short)(s1 + s2);
			block[2+j]	= (short)(s1 - s2);
		}//end for j...

		/// 1-D inverse IT in vert direction.
		for(j = 0; j < 4; j++)
		{
			/// 1st stage.
			int s0 = (int)block[j]					+ (int)block[j+8];
			int s1 = (int)block[j]					- (int)block[j+8];
			int s2 = ((int)block[j+4] >> 1)	- (int)block[j+12];
			int s3 = (int)block[j+4]				+ ((int)block[j+12] >> 1);

			/// 2nd stage.
			block[j]		= (short)((s0 + s3 + 32) >> 6);
			block[12+j]	= (short)((s0 - s3 + 32) >> 6);
			block[4+j]	= (short)((s1 + s2 + 32) >> 6);
			block[8+j]	= (short)((s1 - s2 + 32) >> 6);
		}//end for j...

  }//end if _mode == 0...
	else	///< _mode == 1 IT only.
	{
		/// 1-D inverse IT in horiz direction.
		for(j = 0; j < 16; j += 4)
		{
			/// 1st stage.
			int s0 = (int)block[j]					+ (int)block[2+j];
			int s1 = (int)block[j]					- (int)block[2+j];
			int s2 = (int)(block[1+j] >> 1)	- (int)block[3+j];
			int s3 = (int)block[1+j]				+ (int)(block[3+j] >> 1);

			/// 2nd stage.
			block[j]		= (short)(s0 + s3);
			block[3+j]	= (short)(s0 - s3);
			block[1+j]	= (short)(s1 + s2);
			block[2+j]	= (short)(s1 - s2);
		}//end for j...

		/// 1-D inverse IT in vert direction.
		for(j = 0; j < 4; j++)
		{
			/// 1st stage.
			int s0 = (int)block[j]					+ (int)block[8+j];
			int s1 = (int)block[j]					- (int)block[8+j];
			int s2 = (int)(block[4+j] >> 1)	- (int)block[12+j];
			int s3 = (int)block[4+j]				+ (int)(block[12+j] >> 1);

			/// 2nd stage.
			block[j]		= (short)((s0 + s3 + 32) >> 6);
			block[12+j]	= (short)((s0 - s3 + 32) >> 6);
			block[4+j]	= (short)((s1 + s2 + 32) >> 6);
			block[8+j]	= (short)((s1 - s2 + 32) >> 6);

		}//end for j...

	}//end else...

}//end InverseTransform.

/** Transfer inverse IT.
The inverse IT is performed on the coeffs and are written to 
the output.
@param pCoeff	: Input coeffs.
@param pOut		: Output data.
@return				:	none.
*/
void FastInverse4x4ITImpl1::InverseTransform(void* pCoeff, void* pOut)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pOut, pCoeff, sizeof(short) * 16);
	InverseTransform(pOut);
}//end InverseTransform.

/** Set scaling array.
Each coefficient may be scaled before transforming and therefore 
requires setting up.
@param	pScale:	Scale factor array.
@return				:	none.
*/
void FastInverse4x4ITImpl1::SetScale(void* pScale)
{
	int		i,j,qm;
	int*	ptr = (int *)pScale;

	for(i = 0; i < 16; i++)
		_weightScale[i] = ptr[i];

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm][ColSelector[pos]] * _weightScale[pos];
			}//end for qm & i & j...

}//end SetScale.


void* FastInverse4x4ITImpl1::GetScale(void)
{
	return( (void *)(_weightScale) );
}//end GetScale.

/** Set and get parameters for the implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastInverse4x4ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm					= paramVal % 6;
					_qe					= paramVal/6;
					_f					= 1 << (3-_qe);
					_leftScale	= _qe-4;
					_rightScale	= 4-_qe;
					_q					= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastInverse4x4ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.



========== END FILE: CodecUtils/FastInverse4x4ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastInverse4x4ITImpl1.h ==========
Bundle entry: 45
Original bytes: 4700
Original SHA-256: 5a4290c08ae8682551c34bd70d71837450e7e32b15a7a37e8e10e22840028857
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverse4x4ITImpl1

TAG						: FII4TI1

FILE NAME			: FastInverse4x4ITImpl1.h

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								transform defined by the H.264 standard on the input. 
								It implements the IInverseDct interface. The pre-scaling
								is part of the inverse quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _FASTINVERSE4X4ITIMPL1_H
#define _FASTINVERSE4X4ITIMPL1_H

#pragma once

#include "IInverseTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastInverse4x4ITImpl1 : public IInverseTransform
{
	public:
		FastInverse4x4ITImpl1(void);
		virtual ~FastInverse4x4ITImpl1()	{ }

	/// Interface implementation.
	public:
		/** In-place inverse IT.
		The inverse IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void InverseTransform(void* ptr);

		/** Transfer inverse IT.
		The inverse IT is performed on the coeffs and are written to 
		the output.
		@param pCoeff	: Input coeffs.
		@param pOut		: Output data.
		@return				:	none.
		*/
		virtual void InverseTransform(void* pCoeff, void* pOut);

		/** Set scaling array.
		Each coefficient may be scaled before transforming and therefore 
		requires setting up.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale);
		virtual void* GetScale(void);

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

		/// Constants.
	protected:
		static const int NormAdjust[6][3];
		static const int ColSelector[16];
		
	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		int _weightScale[16];
		int _levelScale[6][16];	///< Pre-calc for each QP % 6.

		/// Hold these members that will only change when q changes.
		int	_q;						///< Current quantisation parameter.
		int	_qm;					///< _q % 6.
		int _qe;					///< _q / 6.
		int _f;						///< Rounding shift = 1 << (3-_qe).
		int _leftScale;		///< Scaling left shift = _qe-4;
		int _rightScale;	///< Scaling right shift = 4-_qe;

};// end class FastInverse4x4ITImpl1.

#endif	//_FASTINVERSE4X4ITIMPL1_H
========== END FILE: CodecUtils/FastInverse4x4ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastInverse4x4On16x16ITImpl1.cpp ==========
Bundle entry: 46
Original bytes: 14051
Original SHA-256: 089dc25d6863ec7d2cf27b9f1b0fe35899110e6ae1eb4102eead5fb79957141b
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverse4x4On16x16ITImpl1

TAG						: FII4O16TI1

FILE NAME			: FastInverse4x4On16x16ITImpl1.cpp

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								transform defined by the H.264 standard on the 16x16
                macroblock input. It implements the IInverseTransform 
                interface. The pre-scaling is part of the inverse 
                quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2011 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastInverse4x4On16x16ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastInverse4x4On16x16ITImpl1::NormAdjust[6][3] =
{
	{10, 16, 13 },
	{11, 18, 14 },
	{13, 20, 16 },
	{14, 23, 18 },
	{16, 25, 20 },
	{18, 29, 23 }
};

const int FastInverse4x4On16x16ITImpl1::ColSelector[16] =
{
	0, 2, 0, 2 ,
	2, 1, 2, 1 ,
	0, 2, 0, 2 ,
	2, 1, 2, 1 
};

/*
--------------------------------------------------------------------------
	Construction.
--------------------------------------------------------------------------
*/
FastInverse4x4On16x16ITImpl1::FastInverse4x4On16x16ITImpl1(void)
{
	int i,j,qm;

	for(i = 0; i < 16; i++)
		_weightScale[i] = 16;	///< For baseline Flat_4x4_16 is default.

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm][ColSelector[pos]] * _weightScale[pos];
			}//end for qm & i & j...

	_mode				= TransformAndQuant;
	_q					= 1;
	_qm					= _q % 6;
	_qe					= _q/6;
	_f					= 1 << (3-_qe);
	_leftScale	= _qe-4;
	_rightScale	= 4-_qe;

}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place inverse Integer Transform.
The 2-D inverse IT is performed on the input coeffs and replaces them. A 1-D
inverse transform is performed on the rows first and then the cols. 
@param ptr	: Data to transform.
@return			:	none.
*/
void FastInverse4x4On16x16ITImpl1::InverseTransform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	if(_mode == QuantOnly)	///< 2 = Q only.
	{
		/// Pre-scaling and quantisation are combined.
		for(int i = 0; i < 16; i++)
    {
      int k = i % 4;
 		  for(j = 0; j < 16; j++)
		  {
        int l = j % 4;
        int x = (int)block[i*16 + j] * _levelScale[_qm][k*4 +l];

			  if( _q < 24 )
					block[i*16 + j] = (short)( (x + _f) >> _rightScale );
				else
					block[i*16 + j] = (short)( x << _leftScale );

		  }//end for j...
    }//end for i...
	}//end if _mode == 2...
	else	///< IT&Q and IT only.
	{
		/// 1-D inverse IT in vert direction.

		if(_mode == TransformAndQuant)	///< 0 = IT&Q.
		{
			for(j = 0; j < 16; j++)
			{
				/// 1st stage with pre-scaling and quantisation.
        int k = j % 4;

				int x0 = (int)block[j]		* _levelScale[_qm][k];
				int x1 = (int)block[j+16]	* _levelScale[_qm][k+4];
				int x2 = (int)block[j+32]	* _levelScale[_qm][k+8];
				int x3 = (int)block[j+48]	* _levelScale[_qm][k+12];

				int x4 = (int)block[j+64]	  * _levelScale[_qm][k];
				int x5 = (int)block[j+80]	  * _levelScale[_qm][k+4];
				int x6 = (int)block[j+96]	  * _levelScale[_qm][k+8];
				int x7 = (int)block[j+112]	* _levelScale[_qm][k+12];

				int x8  = (int)block[j+128]	* _levelScale[_qm][k];
				int x9  = (int)block[j+144]	* _levelScale[_qm][k+4];
				int x10 = (int)block[j+160]	* _levelScale[_qm][k+8];
				int x11 = (int)block[j+176]	* _levelScale[_qm][k+12];

				int x12 = (int)block[j+192]	* _levelScale[_qm][k];
				int x13 = (int)block[j+208]	* _levelScale[_qm][k+4];
				int x14 = (int)block[j+224]	* _levelScale[_qm][k+8];
				int x15 = (int)block[j+240]	* _levelScale[_qm][k+12];

				if(_q < 24)
				{
					x0  = (x0 + _f) >> _rightScale;
					x1  = (x1 + _f) >> _rightScale;
					x2  = (x2 + _f) >> _rightScale;
					x3  = (x3 + _f) >> _rightScale;
					x4  = (x4 + _f) >> _rightScale;
					x5  = (x5 + _f) >> _rightScale;
					x6  = (x6 + _f) >> _rightScale;
					x7  = (x7 + _f) >> _rightScale;
					x8  = (x8 + _f) >> _rightScale;
					x9  = (x9 + _f) >> _rightScale;
					x10 = (x10 + _f) >> _rightScale;
					x11 = (x11 + _f) >> _rightScale;
					x12 = (x12 + _f) >> _rightScale;
					x13 = (x13 + _f) >> _rightScale;
					x14 = (x14 + _f) >> _rightScale;
					x15 = (x15 + _f) >> _rightScale;
				}//end if _q...
				else
				{
					x0  = x0 << _leftScale;
					x1  = x1 << _leftScale;
					x2  = x2 << _leftScale;
					x3  = x3 << _leftScale;
					x4  = x4 << _leftScale;
					x5  = x5 << _leftScale;
					x6  = x6 << _leftScale;
					x7  = x7 << _leftScale;
					x8  = x8 << _leftScale;
					x9  = x9 << _leftScale;
					x10 = x10 << _leftScale;
					x11 = x11 << _leftScale;
					x12 = x12 << _leftScale;
					x13 = x13 << _leftScale;
					x14 = x14 << _leftScale;
					x15 = x15 << _leftScale;
				}//end else...

				int s0 = x0					+ x2;
				int s1 = x0					- x2;
				int s2 = (x1 >> 1)	- x3;
				int s3 = x1					+ (x3 >> 1);

				int s4 = x4					+ x6;
				int s5 = x4					- x6;
				int s6 = (x5 >> 1)	- x7;
				int s7 = x5					+ (x7 >> 1);

				int s8  = x8				+ x10;
				int s9  = x8				- x10;
				int s10 = (x9 >> 1)	- x11;
				int s11 = x9				+ (x11 >> 1);

				int s12 = x12				 + x14;
				int s13 = x12				 - x14;
				int s14 = (x13 >> 1) - x15;
				int s15 = x13				 + (x15 >> 1);

				/// 2nd stage.
				block[j]		= (short)(s0 + s3);
				block[48+j]	= (short)(s0 - s3);
				block[16+j]	= (short)(s1 + s2);
				block[32+j]	= (short)(s1 - s2);

				block[j+64]	  = (short)(s4 + s7);
				block[112+j]	= (short)(s4 - s7);
				block[80+j]	  = (short)(s5 + s6);
				block[96+j]	  = (short)(s5 - s6);

				block[j+128]	= (short)(s8 + s11);
				block[176+j]	= (short)(s8 - s11);
				block[144+j]	= (short)(s9 + s10);
				block[160+j]	= (short)(s9 - s10);

				block[j+192]	= (short)(s12 + s15);
				block[240+j]	= (short)(s12 - s15);
				block[208+j]	= (short)(s13 + s14);
				block[224+j]	= (short)(s13 - s14);

			}//end for j...
		}//end if _mode == 0...
		else	///< _mode == 1 IT only.
		{
			for(j = 0; j < 16; j++)
			{
				/// 1st stage.
				int s0 = (int)block[j]					  + (int)block[32+j];
				int s1 = (int)block[j]					  - (int)block[32+j];
				int s2 = (int)(block[16+j] >> 1)	- (int)block[48+j];
				int s3 = (int)block[16+j]				  + (int)(block[48+j] >> 1);

				int s4 = (int)block[j+64]					+ (int)block[96+j];
				int s5 = (int)block[j+64]					- (int)block[96+j];
				int s6 = (int)(block[80+j] >> 1)	- (int)block[112+j];
				int s7 = (int)block[80+j]				  + (int)(block[112+j] >> 1);

				int s8  = (int)block[j+128]					+ (int)block[160+j];
				int s9  = (int)block[j+128]					- (int)block[160+j];
				int s10 = (int)(block[144+j] >> 1)	- (int)block[176+j];
				int s11 = (int)block[144+j]				  + (int)(block[176+j] >> 1);

				int s12 = (int)block[j+192]					+ (int)block[224+j];
				int s13 = (int)block[j+192]					- (int)block[224+j];
				int s14 = (int)(block[208+j] >> 1)	- (int)block[240+j];
				int s15 = (int)block[208+j]				  + (int)(block[240+j] >> 1);

				/// 2nd stage.
				block[j]		= (short)(s0 + s3);
				block[48+j]	= (short)(s0 - s3);
				block[16+j]	= (short)(s1 + s2);
				block[32+j]	= (short)(s1 - s2);

				block[64+j]		= (short)(s4 + s7);
				block[112+j]	= (short)(s4 - s7);
				block[80+j]	  = (short)(s5 + s6);
				block[96+j]	  = (short)(s5 - s6);

				block[128+j]	= (short)(s8 + s11);
				block[176+j]	= (short)(s8 - s11);
				block[144+j]	= (short)(s9 + s10);
				block[160+j]	= (short)(s9 - s10);

				block[192+j]	= (short)(s12 + s15);
				block[240+j]	= (short)(s12 - s15);
				block[208+j]	= (short)(s13 + s14);
				block[224+j]	= (short)(s13 - s14);

			}//end for j...
		}//end else...

		/// 1-D inverse IT in horiz direction.
		for(j = 0; j < 256; j += 16)
		{
			/// 1st stage.
			int s0 = (int)block[j]					+ (int)block[2+j];
			int s1 = (int)block[j]					- (int)block[2+j];
			int s2 = (int)(block[1+j] >> 1)	- (int)block[3+j];
			int s3 = (int)block[1+j]				+ (int)(block[3+j] >> 1);

			int s4 = (int)block[j+4]					+ (int)block[6+j];
			int s5 = (int)block[j+4]					- (int)block[6+j];
			int s6 = (int)(block[5+j] >> 1)	  - (int)block[7+j];
			int s7 = (int)block[5+j]				  + (int)(block[7+j] >> 1);

			int s8  = (int)block[j+8]					+ (int)block[10+j];
			int s9  = (int)block[j+8]					- (int)block[10+j];
			int s10 = (int)(block[9+j] >> 1)	- (int)block[11+j];
			int s11 = (int)block[9+j]				  + (int)(block[11+j] >> 1);

			int s12 = (int)block[j+12]				+ (int)block[14+j];
			int s13 = (int)block[j+12]				- (int)block[14+j];
			int s14 = (int)(block[13+j] >> 1)	- (int)block[15+j];
			int s15 = (int)block[13+j]				+ (int)(block[15+j] >> 1);

			/// 2nd stage.
			block[j]		= (short)((s0 + s3 + 32) >> 6);
			block[3+j]	= (short)((s0 - s3 + 32) >> 6);
			block[1+j]	= (short)((s1 + s2 + 32) >> 6);
			block[2+j]	= (short)((s1 - s2 + 32) >> 6);

			block[4+j]	= (short)((s4 + s7 + 32) >> 6);
			block[7+j]	= (short)((s4 - s7 + 32) >> 6);
			block[5+j]	= (short)((s5 + s6 + 32) >> 6);
			block[6+j]	= (short)((s5 - s6 + 32) >> 6);

			block[8+j]	= (short)((s8 + s11 + 32) >> 6);
			block[11+j]	= (short)((s8 - s11 + 32) >> 6);
			block[9+j]	= (short)((s9 + s10 + 32) >> 6);
			block[10+j]	= (short)((s9 - s10 + 32) >> 6);

			block[12+j]	= (short)((s12 + s15 + 32) >> 6);
			block[15+j]	= (short)((s12 - s15 + 32) >> 6);
			block[13+j]	= (short)((s13 + s14 + 32) >> 6);
			block[14+j]	= (short)((s13 - s14 + 32) >> 6);

		}//end for j...
	}//end else...

}//end InverseTransform.

/** Transfer inverse IT.
The inverse IT is performed on the coeffs and are written to 
the output.
@param pCoeff	: Input coeffs.
@param pOut		: Output data.
@return				:	none.
*/
void FastInverse4x4On16x16ITImpl1::InverseTransform(void* pCoeff, void* pOut)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pOut, pCoeff, sizeof(short) * 256);
	InverseTransform(pOut);
}//end InverseTransform.

/** Set scaling array.
Each coefficient may be scaled before transforming and therefore 
requires setting up.
@param	pScale:	Scale factor array.
@return				:	none.
*/
void FastInverse4x4On16x16ITImpl1::SetScale(void* pScale)
{
	int		i,j,qm;
	int*	ptr = (int *)pScale;

	for(i = 0; i < 16; i++)
		_weightScale[i] = ptr[i];

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm][ColSelector[pos]] * _weightScale[pos];
			}//end for qm & i & j...

}//end SetScale.


void* FastInverse4x4On16x16ITImpl1::GetScale(void)
{
	return( (void *)(_weightScale) );
}//end GetScale.

/** Set and get parameters for the implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastInverse4x4On16x16ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm					= paramVal % 6;
					_qe					= paramVal/6;
					_f					= 1 << (3-_qe);
					_leftScale	= _qe-4;
					_rightScale	= 4-_qe;
					_q					= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastInverse4x4On16x16ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.



========== END FILE: CodecUtils/FastInverse4x4On16x16ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastInverse4x4On16x16ITImpl1.h ==========
Bundle entry: 47
Original bytes: 4823
Original SHA-256: b0704594a1d085c362985a8c53b9dfaaa10b2f22d5ad912483f0a3a726b4cf40
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverse4x4On16x16ITImpl1

TAG						: FII4O16TI1

FILE NAME			: FastInverse4x4On16x16ITImpl1.h

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								transform defined by the H.264 standard on the 16x16
                macroblock input. It implements the IInverseTransform 
                interface. The pre-scaling is part of the inverse 
                quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2011 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _FASTINVERSE4X4ON16X16ITIMPL1_H
#define _FASTINVERSE4X4ON16X16ITIMPL1_H

#pragma once

#include "IInverseTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastInverse4x4On16x16ITImpl1 : public IInverseTransform
{
	public:
		FastInverse4x4On16x16ITImpl1(void);
		virtual ~FastInverse4x4On16x16ITImpl1()	{ }

	/// Interface implementation.
	public:
		/** In-place inverse IT.
		The inverse IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void InverseTransform(void* ptr);

		/** Transfer inverse IT.
		The inverse IT is performed on the coeffs and are written to 
		the output.
		@param pCoeff	: Input coeffs.
		@param pOut		: Output data.
		@return				:	none.
		*/
		virtual void InverseTransform(void* pCoeff, void* pOut);

		/** Set scaling array.
		Each coefficient may be scaled before transforming and therefore 
		requires setting up.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale);
		virtual void* GetScale(void);

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

		/// Constants.
	protected:
		static const int NormAdjust[6][3];
		static const int ColSelector[16];
		
	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		int _weightScale[16];
		int _levelScale[6][16];	///< Pre-calc for each QP % 6.

		/// Hold these members that will only change when q changes.
		int	_q;						///< Current quantisation parameter.
		int	_qm;					///< _q % 6.
		int _qe;					///< _q / 6.
		int _f;						///< Rounding shift = 1 << (3-_qe).
		int _leftScale;		///< Scaling left shift = _qe-4;
		int _rightScale;	///< Scaling right shift = 4-_qe;

};// end class FastInverse4x4On16x16ITImpl1.

#endif	//_FASTINVERSE4X4ON16X16ITIMPL1_H
========== END FILE: CodecUtils/FastInverse4x4On16x16ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastInverseDC2x2ITImpl1.cpp ==========
Bundle entry: 48
Original bytes: 7358
Original SHA-256: 790d1990456483b9da695b0cce3b19615eeb4aef279303b84bae643c2d4ebf3b
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverseDC2x2ITImpl1

TAG						: FIDC2ITI1

FILE NAME			: FastInverseDC2x2ITImpl1.cpp

DESCRIPTION		: A class to implement a fast inverse 2x2 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IInverseTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastInverseDC2x2ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastInverseDC2x2ITImpl1::NormAdjust[6] =
{
	10, 
	11, 
	13, 
	14, 
	16, 
	18
};

/*
--------------------------------------------------------------------------
	Construction.
--------------------------------------------------------------------------
*/
FastInverseDC2x2ITImpl1::FastInverseDC2x2ITImpl1(void)
{
	int i,j,qm;

	for(i = 0; i < 4; i++)
		_weightScale[i] = 16;	///< Flat_4x4_16 is default.

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 2; i++)
			for(j = 0; j < 2; j++)
			{
				int pos = 2*i + j;
				_levelScale[qm][pos] = NormAdjust[qm] * _weightScale[pos];
			}//end for qm & i & j...

	_mode = 0;
	_q					= 1;
	_qm					= _q % 6;
	_qe					= _q/6;
	_leftScale	= _qe;
	_rightScale	= 5;
}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place inverse Integer Transform.
The 2-D inverse IT is performed on the input coeffs and replaces them. A 1-D
inverse transform is performed on the rows first and then the cols. 
@param ptr	: Data to transform.
@return			:	none.
*/
void FastInverseDC2x2ITImpl1::InverseTransform(void* ptr)
{
	short* block = (short *)ptr;

	if(_mode != QuantOnly)	///< IT&Q and IT only.
	{
		/// 1st stage inverse transform.
		int s0 = (int)(block[0]	+ block[1]);
		int s2 = (int)(block[0] - block[1]);
		int s1 = (int)(block[2] + block[3]);
		int s3 = (int)(block[2]	- block[3]);

		if(_mode == TransformAndQuant)	///< 0 = IT&Q.
		{
			/// 2nd stage with post-scaling and quantisation.
			int x0	= (s0 + s1) * _levelScale[_qm][0];
			int x2	= (s0 - s1) * _levelScale[_qm][2];
			int x1	= (s2 + s3) * _levelScale[_qm][1];
			int x3	= (s2 - s3) * _levelScale[_qm][3];

			block[0]	= (short)((x0 << _leftScale) >> _rightScale);
			block[1]	= (short)((x1 << _leftScale) >> _rightScale);
			block[2]	= (short)((x2 << _leftScale) >> _rightScale);
			block[3]	= (short)((x3 << _leftScale) >> _rightScale);

		}//end if _mode == 0...
		else	///< _mode == 1 IT only.
		{
			/// 2nd stage transform.
			block[0]	= (short)(s0 + s1);
			block[2]	= (short)(s0 - s1);
			block[1]	= (short)(s2 + s3);
			block[3]	= (short)(s2 - s3);
		}//end else...

	}//end if _mode != 2...
	else	///< _mode 2 = Q only.
	{
		/// Post-scaling and quantisation are combined.
		int i;
		for(i = 0; i < 4; i++)
		{
			int x = (int)block[i] * _levelScale[_qm][i];
			block[i]	= (short)((x << _leftScale) >> _rightScale);
		}//end for i...
	}//end else...

}//end InverseTransform.

/** Transfer inverse IT.
The inverse IT is performed on the coeffs and are written to 
the output.
@param pCoeff	: Input coeffs.
@param pOut		: Output data.
@return				:	none.
*/
void FastInverseDC2x2ITImpl1::InverseTransform(void* pCoeff, void* pOut)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pOut, pCoeff, sizeof(short) * 4);
	InverseTransform(pOut);
}//end InverseTransform.

/** Set scaling array.
Each coefficient may be scaled before transforming and therefore 
requires setting up.
@param	pScale:	Scale factor array.
@return				:	none.
*/
void FastInverseDC2x2ITImpl1::SetScale(void* pScale)
{
	int		i,j,qm;
	int*	ptr = (int *)pScale;

	for(i = 0; i < 4; i++)
		_weightScale[i] = ptr[i];

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 2; i++)
			for(j = 0; j < 2; j++)
			{
				int pos = 2*i + j;
				_levelScale[qm][pos] = NormAdjust[qm] * _weightScale[pos];
			}//end for qm & i & j...

}//end SetScale.


void* FastInverseDC2x2ITImpl1::GetScale(void)
{
	return( (void *)(_weightScale) );
}//end GetScale.

/** Set and get parameters for the implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastInverseDC2x2ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm					= paramVal % 6;
					_qe					= paramVal/6;
					_leftScale	= _qe;
					_rightScale	= 5;
					_q					= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastInverseDC2x2ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.


========== END FILE: CodecUtils/FastInverseDC2x2ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastInverseDC2x2ITImpl1.h ==========
Bundle entry: 49
Original bytes: 4683
Original SHA-256: 6ced9c5a70868a59c86148951dba9b5fb3108cf7df61143081b8e074fecd084d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverseDC2x2ITImpl1

TAG						: FIDC2ITI1

FILE NAME			: FastInverseDC2x2ITImpl1.h

DESCRIPTION		: A class to implement a fast inverse 2x2 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IInverseTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _FASTINVERSEDC2X2ITIMPL1_H
#define _FASTINVERSEDC2X2ITIMPL1_H

#pragma once

#include "IInverseTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastInverseDC2x2ITImpl1 : public IInverseTransform
{
	public:
		FastInverseDC2x2ITImpl1(void);
		virtual ~FastInverseDC2x2ITImpl1()	{ }

	/// Interface implementation.
	public:
		/** In-place inverse IT.
		The inverse IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void InverseTransform(void* ptr);

		/** Transfer inverse IT.
		The inverse IT is performed on the coeffs and are written to 
		the output.
		@param pCoeff	: Input coeffs.
		@param pOut		: Output data.
		@return				:	none.
		*/
		virtual void InverseTransform(void* pCoeff, void* pOut);

		/** Set scaling array.
		Each coefficient may be scaled before transforming and therefore 
		requires setting up.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale);
		virtual void* GetScale(void);

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		Undefined for this implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

		/// Constants.
	protected:
		static const int NormAdjust[6];
		
	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		int _weightScale[4];
		int _levelScale[6][4];	///< Pre-calc for each QP % 6.

		/// Hold these members that will only change when q changes.
		int	_q;						///< Current quantisation parameter.
		int	_qm;					///< _q % 6.
		int _qe;					///< _q / 6.
		int _leftScale;		///< Scaling left shift = _qe;
		int _rightScale;	///< Scaling right shift = 5;

};// end class FastInverseDC2x2ITImpl1.

#endif	//_FASTINVERSEDC2X2ITIMPL1_H
========== END FILE: CodecUtils/FastInverseDC2x2ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/FastInverseDC4x4ITImpl1.cpp ==========
Bundle entry: 50
Original bytes: 8719
Original SHA-256: f13accceabb6245c15a6c9de302c1141586efc4868e3f86987f0d9f573f59ed2
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverseDC4x4ITImpl1

TAG						: FIDC4ITI1

FILE NAME			: FastInverseDC4x4ITImpl1.cpp

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IInverseTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

==========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "FastInverseDC4x4ITImpl1.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
const int FastInverseDC4x4ITImpl1::NormAdjust[6] =
{
	10, 
	11, 
	13, 
	14, 
	16, 
	18
};

/*
--------------------------------------------------------------------------
	Construction.
--------------------------------------------------------------------------
*/
FastInverseDC4x4ITImpl1::FastInverseDC4x4ITImpl1(void)
{
	int i,j,qm;

	for(i = 0; i < 16; i++)
		_weightScale[i] = 16;	///< Flat_4x4_16 is default.

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm] * _weightScale[pos];
			}//end for qm & i & j...

	_mode				= 0;
	_q					= 1;
	_qm					= _q % 6;
	_qe					= _q/6;
	_f					= 1 << (5-_qe);
	_leftScale	= _qe-6;
	_rightScale	= 6-_qe;
}//end constructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** In-place inverse Integer Transform.
The 2-D inverse IT is performed on the input coeffs and replaces them. A 1-D
inverse transform is performed on the rows first and then the cols. 
@param ptr	: Data to transform.
@return			:	none.
*/
void FastInverseDC4x4ITImpl1::InverseTransform(void* ptr)
{
	short* block = (short *)ptr;
	int j;

	if(_mode != QuantOnly)	///< IT&Q and IT only.
	{
		/// 1-D inverse IT in vert direction.
		for(j = 0; j < 4; j++)
		{
			/// 1st stage.
			int s0 = (int)block[j]		+ (int)block[8+j];
			int s1 = (int)block[j]		- (int)block[8+j];
			int s2 = (int)block[4+j]	- (int)block[12+j];
			int s3 = (int)block[4+j]	+ (int)block[12+j];

			/// 2nd stage.
			block[j]		= (short)(s0 + s3);
			block[12+j]	= (short)(s0 - s3);
			block[4+j]	= (short)(s1 + s2);
			block[8+j]	= (short)(s1 - s2);
		}//end for j...

		if(_mode == TransformAndQuant)	///< 0 = IT&Q.
		{
			/// 1-D inverse IT in horiz direction.
			for(j = 0; j < 16; j += 4)
			{
				/// 1st stage.
				int s0 = (int)block[j]		+ (int)block[2+j];
				int s1 = (int)block[j]		- (int)block[2+j];
				int s2 = (int)block[1+j]	- (int)block[3+j];
				int s3 = (int)block[1+j]	+ (int)block[3+j];

				/// 2nd stage with post-scaling and quantisation.
				int x0	= (s0 + s3) * _levelScale[_qm][j];
				int x3	= (s0 - s3) * _levelScale[_qm][j+3];
				int x1	= (s1 + s2) * _levelScale[_qm][j+1];
				int x2	= (s1 - s2) * _levelScale[_qm][j+2];

				if(_q < 36)
				{
					block[j]		= (short)((x0 + _f) >> _rightScale);
					block[j+1]	= (short)((x1 + _f) >> _rightScale);
					block[j+2]	= (short)((x2 + _f) >> _rightScale);
					block[j+3]	= (short)((x3 + _f) >> _rightScale);
				}//end if _q...
				else
				{
					block[j]		= (short)(x0 << _leftScale);
					block[j+1]	= (short)(x1 << _leftScale);
					block[j+2]	= (short)(x2 << _leftScale);
					block[j+3]	= (short)(x3 << _leftScale);
				}//end else...
			}//end for j...
		}//end if _mode == 0...
		else	///< _mode == 1 IT only.
		{
			/// 1-D inverse IT in horiz direction.
			for(j = 0; j < 16; j += 4)
			{
				/// 1st stage.
				int s0 = (int)block[j]		+ (int)block[2+j];
				int s1 = (int)block[j]		- (int)block[2+j];
				int s2 = (int)block[1+j]	- (int)block[3+j];
				int s3 = (int)block[1+j]	+ (int)block[3+j];

				/// 2nd stage.
				block[j]		= (short)(s0 + s3);
				block[3+j]	= (short)(s0 - s3);
				block[1+j]	= (short)(s1 + s2);
				block[2+j]	= (short)(s1 - s2);
			}//end for j...
		}//end else...

	}//end if _mode != 2...
	else	///< _mode 2 = Q only.
	{
		/// Post-scaling and quantisation are combined.
		int i;
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int x = (int)block[i*4 + j] * _levelScale[_qm][i*4 +j];
				if(_q < 36)
					block[i*4 + j] = (short)( (x + _f) >> _rightScale );
				else
					block[i*4 + j] = (short)( x << _leftScale );
			}//end for i & j...
	}//end else...

}//end InverseTransform.

/** Transfer inverse IT.
The inverse IT is performed on the coeffs and are written to 
the output.
@param pCoeff	: Input coeffs.
@param pOut		: Output data.
@return				:	none.
*/
void FastInverseDC4x4ITImpl1::InverseTransform(void* pCoeff, void* pOut)
{
	/// Copy to output and then do in-place inverse transform.
	memcpy(pOut, pCoeff, sizeof(short) * 16);
	InverseTransform(pOut);
}//end InverseTransform.

/** Set scaling array.
Each coefficient may be scaled before transforming and therefore 
requires setting up.
@param	pScale:	Scale factor array.
@return				:	none.
*/
void FastInverseDC4x4ITImpl1::SetScale(void* pScale)
{
	int		i,j,qm;
	int*	ptr = (int *)pScale;

	for(i = 0; i < 16; i++)
		_weightScale[i] = ptr[i];

	for(qm = 0; qm < 6; qm++)
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
			{
				int pos = 4*i + j;
				_levelScale[qm][pos] = NormAdjust[qm] * _weightScale[pos];
			}//end for qm & i & j...

}//end SetScale.


void* FastInverseDC4x4ITImpl1::GetScale(void)
{
	return( (void *)(_weightScale) );
}//end GetScale.

/** Set and get parameters for the implementation.
@param paramID	: Parameter to set/get.
@param paramVal	: Parameter value.
@return					: None (Set) or the param value (Get).
*/
void FastInverseDC4x4ITImpl1::SetParameter(int paramID, int paramVal)
{
	switch(paramID)
	{
		case QUANT_ID:
			{
				// TODO: Put these calcs into a table.
				if(paramVal != _q)	///< Do we need to change member values or keep previous?
				{
					_qm					= paramVal % 6;
					_qe					= paramVal/6;
					_f					= 1 << (5-_qe);
					_leftScale	= _qe-6;
					_rightScale	= 6-_qe;
					_q					= paramVal;
				}//end if q...
			}//end case QUANT_ID...
			break;
		default :
			/// Do nothing.
			break;
	}//end switch paramID...
}//end SetParameter.

int FastInverseDC4x4ITImpl1::GetParameter(int paramID)
{
	int ret;
	switch(paramID)
	{
		case QUANT_ID:
			ret = _q;
			break;
		default :
			ret = _q;	///< Quant value is returned as default.
			break;
	}//end switch paramID...

	return(ret);
}//end GetParameter.


========== END FILE: CodecUtils/FastInverseDC4x4ITImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/FastInverseDC4x4ITImpl1.h ==========
Bundle entry: 51
Original bytes: 4744
Original SHA-256: 6d4d827c2402d9028c51c913659d4eee910499c40598bfa2422591625044e4c7
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: FastInverseDC4x4ITImpl1

TAG						: FIDC4ITI1

FILE NAME			: FastInverseDC4x4ITImpl1.h

DESCRIPTION		: A class to implement a fast inverse 4x4 2-D integer
								Hardamard transform defined by the H.264 (03/2005) 
								standard on the input. It implements the 
								IInverseTransform interface. The scaling is part of 
								the quantisation process.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

==========================================================================================
*/
#ifndef _FASTINVERSEDC4X4ITIMPL1_H
#define _FASTINVERSEDC4X4ITIMPL1_H

#pragma once

#include "IInverseTransform.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class FastInverseDC4x4ITImpl1 : public IInverseTransform
{
	public:
		FastInverseDC4x4ITImpl1(void);
		virtual ~FastInverseDC4x4ITImpl1()	{ }

	/// Interface implementation.
	public:
		/** In-place inverse IT.
		The inverse IT is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void InverseTransform(void* ptr);

		/** Transfer inverse IT.
		The inverse IT is performed on the coeffs and are written to 
		the output.
		@param pCoeff	: Input coeffs.
		@param pOut		: Output data.
		@return				:	none.
		*/
		virtual void InverseTransform(void* pCoeff, void* pOut);

		/** Set scaling array.
		Each coefficient may be scaled before transforming and therefore 
		requires setting up.
		@param	pScale:	Scale factor array.
		@return				:	none.
		*/
		virtual void	SetScale(void* pScale);
		virtual void* GetScale(void);

		/** Set/Get the mode of operation.
		Allow an implementation to define modes of operation or
		interpretation of the quantisation process.
		@param mode	: Mode to set.
		@return			: none.
		*/
		virtual void SetMode(int mode) { _mode = mode; }
		virtual int  GetMode(void) { return(_mode); }

		/** Set and get parameters for the implementation.
		Undefined for this implementation.
		@param paramID	: Parameter to set/get.
		@param paramVal	: Parameter value.
		@return					: None (Set) or the param value (Get).
		*/
		virtual void	SetParameter(int paramID, int paramVal);
		virtual int		GetParameter(int paramID);

		/// Constants.
	protected:
		static const int NormAdjust[6];
		
	protected:
		int _mode;	///< 0 = IT+Q, 1 = IT only, 2 = Q only.

		int _weightScale[16];
		int _levelScale[6][16];	///< Pre-calc for each QP % 6.

		/// Hold these members that will only change when q changes.
		int	_q;						///< Current quantisation parameter.
		int	_qm;					///< _q % 6.
		int _qe;					///< _q / 6.
		int _f;						///< Rounding shift = 1 << (3-_qe).
		int _leftScale;		///< Scaling left shift = _qe-4;
		int _rightScale;	///< Scaling right shift = 4-_qe;

};// end class FastInverseDC4x4ITImpl1.

#endif	//_FASTINVERSEDC4X4ITIMPL1_H
========== END FILE: CodecUtils/FastInverseDC4x4ITImpl1.h ==========

========== BEGIN FILE: CodecUtils/H263MotionVectorPredictorImpl1.cpp ==========
Bundle entry: 52
Original bytes: 5442
Original SHA-256: 1b2186865f978c8bb6cc97d0b54010a738b2c84d6b54a876889b1650d6a4f563
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H263MotionVectorPredictorImpl1

TAG						: H263MVPI1

FILE NAME			: H263MotionVectorPredictorImpl1.cpp

DESCRIPTION		: A class to predicting motion vectors from the surrounding motion
                vectors of previously encoded/decoded macroblocks. Implements the 
                IMotionVectorPredictor() interface.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "H263MotionVectorPredictorImpl1.h"
#include "VectorStructList.h"

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

/*
--------------------------------------------------------------------------
  Public IMotionVectorPredictor Interface. 
--------------------------------------------------------------------------
*/

/** Get the 16x16 2-D prediction for the macroblock/block.
@param pList	: Input list of motion vectors.
@param blk		: Macroblock/block number to get the prediction for.
@param predX  : Output predicted X coordinate
@param predX  : Output predicted Y coordinate
@return	      :	1 = success, 0 = failure.
*/
int H263MotionVectorPredictorImpl1::Get16x16Prediction(	void* pList, int blk, int* predX, int* predY)
{
  VectorStructList* pVL = (VectorStructList *)pList;  ///< Typecast input vector list.

	/// Find the current coords in macroblock units.
	int mby			= blk/_widthInMbs;
	int mbx			= blk % _widthInMbs;

	/// Macroblock to the left.
	int mv1x = 0;
	int mv1y = 0;
	int mb1x = mbx - 1;
	if(mb1x >= 0) ///< Is not outside of the left edge.
	{
		int pos = (mby * _widthInMbs) + mb1x;
		mv1x = pVL->GetSimpleElement(pos, 0);
		mv1y = pVL->GetSimpleElement(pos, 1);
	}//end if mb1...

	/// Macroblock above.
	int mv2x = 0;
	int mv2y = 0;
	int mb2y = mby - 1;
	if(mb2y >= 0) ///< Is not outside the top edge.
	{
		int pos = (mb2y * _widthInMbs) + mbx;
		mv2x = pVL->GetSimpleElement(pos, 0);
		mv2y = pVL->GetSimpleElement(pos, 1);
	}//end if mb2y...
	else
	{
		/// The macroblock motion vector to the left is the predictor
		/// if at top edge, including the top right corner. Note that 
		/// it will also be [0,0] if it is the top left corner macroblock.
		*predX = mv1x;
		*predY = mv1y;
		return(1);
	}//end else...

	/// Macroblock above right.
	int mv3x = 0;
	int mv3y = 0;
	int mb3x = mbx + 1;
	int mb3y = mby - 1;
	if(mb3x < _widthInMbs) ///< Is not outside of the right edge.
	{
		int pos = (mb3y * _widthInMbs) + mb3x;
		mv3x = pVL->GetSimpleElement(pos, 0);
		mv3y = pVL->GetSimpleElement(pos, 1);
	}//end if mb1...

	/// Require the median of each vector component as the predictor.
	*predX = Median(mv1x, mv2x, mv3x);
	*predY = Median(mv1y, mv2y, mv3y);

  return(1);
}//end Get16x16Prediction. 

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

/** Calc the median of 3 numbers.
@param x	:	1st num.
@param y	:	2nd num.
@param z	:	3rd num.
@return		: The median of x, y and z.
*/
int H263MotionVectorPredictorImpl1::Median(int x, int y, int z)
{
	int min,max;

	// min = MIN(x,MIN(y,z)) and max = MAX(x,MAX(y,z)).
	if( (y - z) < 0 )	{	min = y;	max = z;	}
	else { min = z; max = y; }
	if(x < min) min = x;
	if(x > max) max = x;
	// Median.
	int result = x + y + z - min - max;

	return(result);
}//end Median.



========== END FILE: CodecUtils/H263MotionVectorPredictorImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/H263MotionVectorPredictorImpl1.h ==========
Bundle entry: 53
Original bytes: 3800
Original SHA-256: 2612310a714f8e641a0010731f3d66fed10e5de82a1cb546b1b455bfc5349941
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H263MotionVectorPredictorImpl1

TAG						: H263MVPI1

FILE NAME			: H263MotionVectorPredictorImpl1.h

DESCRIPTION		: A class to predicting motion vectors from the surrounding motion
                vectors of previously encoded/decoded macroblocks. Implements the 
                IMotionVectorPredictor() interface.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _H263MOTIONVECTORPREDICTOR_H
#define _H263MOTIONVECTORPREDICTOR_H

#include "IMotionVectorPredictor.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class H263MotionVectorPredictorImpl1 : public IMotionVectorPredictor
{
/// Construction.
public:

  H263MotionVectorPredictorImpl1(int imgWidth, int imgHeight) { _widthInMbs = imgWidth/16; _heightInMbs = imgHeight/16; }

  virtual ~H263MotionVectorPredictorImpl1(void) {}

/// IMotionVectorPredictor Interface.
public:
  virtual int	Create(void) { return(1); }

	/** Get the 16x16 2-D prediction for the macroblock/block.
	@param pList	: Input list of motion vectors.
	@param blk		: Macroblock/block number to get the prediction for.
  @param predX  : Output predicted X coordinate
  @param predX  : Output predicted Y coordinate
	@return	      :	1 = success, 0 = failure.
	*/
	virtual int Get16x16Prediction(	void* pList, int blk, int* predX, int* predY);

/// Local methods.
protected:

  /** Calc the median of 3 numbers.
  @param x	:	1st num.
  @param y	:	2nd num.
  @param z	:	3rd num.
  @return		: The median of x, y and z.
  */
  int Median(int x, int y, int z);

/// Local members.
protected:

	// Parameters must remain const for the life time of this instantiation.
	int	_widthInMbs;		///< Width of the img in macroblock units.
	int	_heightInMbs;	  ///< Height of the img in macroblock units.

};//end H263MotionVectorPredictorImpl1.

#endif // !_H263MOTIONVECTORPREDICTOR_H

========== END FILE: CodecUtils/H263MotionVectorPredictorImpl1.h ==========

========== BEGIN FILE: CodecUtils/H264BitStreamReader.cpp ==========
Bundle entry: 54
Original bytes: 5311
Original SHA-256: c6e46dabad746b2d11b39faee7bf37e7c611974249e5876d61d8b74c65007858
Decoded as: utf-8
---------- SOURCE TEXT ----------
#include "H264BitStreamReader.h"
#include <algorithm>

H264BitStreamReader::H264BitStreamReader()
: _bitStream(NULL),
  _physicalBitSize(0),
  _logicalBitSize(0),
  _logicalBytePos(0),
  _physicalBytePos(0),
  _bitPos(7),
  _nextSkip(0)
{
}

H264BitStreamReader::~H264BitStreamReader()
{
}

void H264BitStreamReader::SetStream(void* stream, int bitSize)
{
  _bitStream = (unsigned char*)stream;
  _physicalBitSize = bitSize;
  _skipBytePos.clear();

  const int byteCount = (bitSize + 7) / 8;
  if(_bitStream != NULL)
  {
    for(int i = 2; i < byteCount; ++i)
    {
      if((_bitStream[i] == 0x03) &&
         (_bitStream[i - 1] == 0x00) &&
         (_bitStream[i - 2] == 0x00))
      {
        _skipBytePos.push_back(i);
        ++i; // Preserve the old unescaper's handling of 00 00 03 03.
      }
    }
  }

  _logicalBitSize = bitSize - ((int)_skipBytePos.size() * 8);
  Reset();
}

void* H264BitStreamReader::GetStream(void)
{
  return (void*)_bitStream;
}

void H264BitStreamReader::Reset(void)
{
  _logicalBytePos = 0;
  _physicalBytePos = 0;
  _bitPos = 7;
  _nextSkip = 0;

  while((_nextSkip < (int)_skipBytePos.size()) &&
        (_skipBytePos[_nextSkip] == _physicalBytePos))
  {
    ++_physicalBytePos;
    ++_nextSkip;
  }
}

void H264BitStreamReader::AdvanceByte(void)
{
  ++_logicalBytePos;
  ++_physicalBytePos;

  // This test is performed only at byte boundaries, not for every decoded bit
  // and not in any pixel loop.
  if((_nextSkip < (int)_skipBytePos.size()) &&
     (_physicalBytePos == _skipBytePos[_nextSkip]))
  {
    ++_physicalBytePos;
    ++_nextSkip;
  }
}

int H264BitStreamReader::Read(void)
{
  const int codeBit = (int)((_bitStream[_physicalBytePos] >> _bitPos) & 1);

  if(_bitPos > 0)
    --_bitPos;
  else
  {
    _bitPos = 7;
    AdvanceByte();
  }

  return codeBit;
}

int H264BitStreamReader::Read(int numBits)
{
  unsigned int code = 0;

  while(numBits > 0)
  {
    const int available = _bitPos + 1;
    const int take = (numBits < available) ? numBits : available;
    const int shift = available - take;
    const unsigned int mask = (take == 8) ? 0xFFu : ((1u << take) - 1u);

    code = (code << take) |
      (((unsigned int)_bitStream[_physicalBytePos] >> shift) & mask);

    _bitPos -= take;
    numBits -= take;

    if(_bitPos < 0)
    {
      _bitPos = 7;
      AdvanceByte();
    }
  }

  return (int)code;
}

int H264BitStreamReader::Peek(int bitLoc, int numBits)
{
  const int saveLogicalByte = _logicalBytePos;
  const int savePhysicalByte = _physicalBytePos;
  const int saveBit = _bitPos;
  const int saveNextSkip = _nextSkip;

  if(!Seek(bitLoc))
    return 0;

  const int code = Read(numBits);

  _logicalBytePos = saveLogicalByte;
  _physicalBytePos = savePhysicalByte;
  _bitPos = saveBit;
  _nextSkip = saveNextSkip;

  return code;
}

int H264BitStreamReader::NextSkipIndex(int physicalByte) const
{
  return (int)(std::upper_bound(_skipBytePos.begin(),
                               _skipBytePos.end(),
                               physicalByte) - _skipBytePos.begin());
}

int H264BitStreamReader::PhysicalByteFromLogical(int logicalByte) const
{
  int physicalByte = logicalByte;

  // A skipped physical byte increases the mapping by one. Usually this loop
  // executes once; it repeats only when several prevention bytes precede the
  // requested logical position.
  for(;;)
  {
    const int skipped = (int)(std::upper_bound(_skipBytePos.begin(),
                                               _skipBytePos.end(),
                                               physicalByte) -
                              _skipBytePos.begin());
    const int mapped = logicalByte + skipped;
    if(mapped == physicalByte)
      return physicalByte;
    physicalByte = mapped;
  }
}

int H264BitStreamReader::Seek(int streamBitPos)
{
  if((streamBitPos < 0) || (streamBitPos >= _logicalBitSize))
    return 0;

  _logicalBytePos = streamBitPos / 8;
  _bitPos = streamBitPos % 8;
  _physicalBytePos = PhysicalByteFromLogical(_logicalBytePos);
  _nextSkip = NextSkipIndex(_physicalBytePos);
  return 1;
}

int H264BitStreamReader::GetStreamBitPos(void)
{
  return (_logicalBytePos << 3) + _bitPos;
}

int H264BitStreamReader::GetStreamBytePos(void)
{
  return _logicalBytePos;
}

void H264BitStreamReader::SetStreamBitSize(int bitSize)
{
  _logicalBitSize = bitSize;
}

int H264BitStreamReader::GetStreamBitSize(void)
{
  return _logicalBitSize;
}

int H264BitStreamReader::GetStreamBitsRemaining(void)
{
  return _logicalBitSize - ((_logicalBytePos << 3) + (7 - _bitPos));
}

void H264BitStreamReader::Copy(IBitStreamReader* pFrom)
{
  // H264v2Codec now creates this reader for both the persistent reader and
  // its temporary SPS/PPS state copy, so the concrete type is guaranteed.
  H264BitStreamReader* p = (H264BitStreamReader*)pFrom;

  _bitStream = p->_bitStream;
  _physicalBitSize = p->_physicalBitSize;
  _logicalBitSize = p->_logicalBitSize;
  _logicalBytePos = p->_logicalBytePos;
  _physicalBytePos = p->_physicalBytePos;
  _bitPos = p->_bitPos;
  _nextSkip = p->_nextSkip;
  _skipBytePos = p->_skipBytePos;
}
========== END FILE: CodecUtils/H264BitStreamReader.cpp ==========

========== BEGIN FILE: CodecUtils/H264BitStreamReader.h ==========
Bundle entry: 55
Original bytes: 1195
Original SHA-256: b8ff7188b726e25ff16d2e191d8fe159dd0c6c01436947af60956a456c28fbba
Decoded as: utf-8
---------- SOURCE TEXT ----------
#ifndef _H264BITSTREAMREADER_H
#define _H264BITSTREAMREADER_H

#pragma once

#include <vector>
#include "IBitStreamReader.h"

// Read-only MSB-first H.264 reader. 00 00 03 emulation-prevention bytes are
// omitted logically; the caller-owned compressed buffer is never modified.
class H264BitStreamReader : public IBitStreamReader
{
public:
  H264BitStreamReader();
  virtual ~H264BitStreamReader();

  int Read(void);
  int Read(int numBits);
  int Peek(int bitLoc, int numBits);

  void SetStream(void* stream, int bitSize);
  void* GetStream(void);
  void Reset(void);
  int Seek(int streamBitPos);
  int GetStreamBitPos(void);
  int GetStreamBytePos(void);
  void SetStreamBitSize(int bitSize);
  int GetStreamBitSize(void);
  int GetStreamBitsRemaining(void);
  void Copy(IBitStreamReader* pFrom);

private:
  void AdvanceByte(void);
  int PhysicalByteFromLogical(int logicalByte) const;
  int NextSkipIndex(int physicalByte) const;

private:
  unsigned char* _bitStream;
  int _physicalBitSize;
  int _logicalBitSize;
  int _logicalBytePos;
  int _physicalBytePos;
  int _bitPos;
  int _nextSkip;
  std::vector<int> _skipBytePos;
};

#endif
========== END FILE: CodecUtils/H264BitStreamReader.h ==========

========== BEGIN FILE: CodecUtils/H264MbImgCache.cpp ==========
Bundle entry: 56
Original bytes: 7165
Original SHA-256: f44c6c4d6ba03df62f28dc9df143e8ffc7a956c10820c05e8080f34efcbd446f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264MbImgCache

TAG						: H264MIC

FILE NAME			: H264MbImgCache.cpp

DESCRIPTION		: A class to cache image blocks aligned with H.264 macroblocks data.

COPYRIGHT			:	(c)CSIR 2007-2014 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#include <string.h>
#endif

#include <memory.h>
#include "H264MbImgCache.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
H264MbImgCache::H264MbImgCache(void)
{
  /// Image references.
  _lum = NULL;
  _cb  = NULL;
  _cr  = NULL;

  /// Cache blocks and overlays.
  _plumCache  = NULL;
  _lum16x16   = NULL;
  _pCbCache   = NULL;
  _cb8x8      = NULL;
  _pCrCache   = NULL;
  _cr8x8      = NULL;

}//end constructor.

H264MbImgCache::~H264MbImgCache(void)
{
	Destroy();
}//end destructor.

void H264MbImgCache::Destroy(void)
{
	if(_lum16x16 != NULL)
		delete _lum16x16;
	_lum16x16 = NULL;
	if(_plumCache != NULL)
		delete[] _plumCache;
	_plumCache = NULL;

	if(_cb8x8 != NULL)
		delete _cb8x8;
	_cb8x8 = NULL;
	if(_pCbCache != NULL)
		delete[] _pCbCache;
	_pCbCache = NULL;

	if(_cr8x8 != NULL)
		delete _cr8x8;
	_cr8x8 = NULL;
	if(_pCrCache != NULL)
		delete[] _pCrCache;
	_pCrCache = NULL;

}//end Destroy.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Create mem container.
Set the mem for a 16x16 lum and two 8x8 chr blocks with their overlays.
@return			: 1 = success, 0 = failed.
*/
int H264MbImgCache::Create(void)
{
  /// Clean out before starting.
  Destroy();

	_plumCache = new short[256];	///< 16x16 block.
	_lum16x16	= new OverlayMem2Dv2(_plumCache, 16, 16, 16, 16);
	_pCbCache = new short[64];	///< 8x8 blocks for predicition operations.
	_cb8x8	= new OverlayMem2Dv2(_pCbCache, 8, 8, 8, 8);
	_pCrCache = new short[64];
	_cr8x8	= new OverlayMem2Dv2(_pCrCache, 8, 8, 8, 8);

  if( (_plumCache == NULL)||(_lum16x16 == NULL) ||																
			(_pCbCache == NULL) ||(_cb8x8 == NULL) || 
			(_pCrCache == NULL) ||(_cr8x8 == NULL) )
  {
    Destroy();
	  return(0);
  }//end if !_plumCache...

  return(1);
}//end Create.

/** Cache the mb aligned image.
Use the mb data to align the mb with the image position and copy the image
data into the cache image. NOTE: No mem checking is done so SetImage() must 
have been called before this method can be used.
@param  pMb : Mb to cache.
@return			: 1 = success, 0 = failed.
*/
int H264MbImgCache::Cache(MacroBlockH264* pMb)
{
  /// Align the Lum img block with this mb position
	_lum->SetOverlayDim(16, 16);
	_lum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
  /// Read from the Lum img block into the mb cache.
  _lum->Read(*(_lum16x16));
  
  /// Align the Cb img block with this mb position
	_cb->SetOverlayDim(8, 8);
	_cb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  /// Read from the Cb img block into the mb cache.
  _cb->Read(*(_cb8x8));

  /// Align the Cr img block with this mb position
	_cr->SetOverlayDim(8, 8);
	_cr->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  /// Read from the Cr img block into the mb cache.
  _cr->Read(*(_cr8x8));

  return(1);
}//end Cache.

/** Restore the mb aligned image from the cache.
Use the mb data to align the mb with the image position and copy the cache
data into the image. NOTE: No mem checking is done so SetImage() must 
have been called before this method can be used.
@param  pMb : Mb to restore.
@return			: 1 = success, 0 = failed.
*/
int H264MbImgCache::Restore(MacroBlockH264* pMb)
{
  /// Align the Lum img block with this mb position
	_lum->SetOverlayDim(16, 16);
	_lum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
  /// Read from the mb cache into the Lum img block .
  _lum16x16->Read(*(_lum));
  
  /// Align the Cb img block with this mb position
	_cb->SetOverlayDim(8, 8);
	_cb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  /// Read from the mb cache into the Cb img block .
  _cb8x8->Read(*(_cb));

  /// Align the Cr img block with this mb position
	_cr->SetOverlayDim(8, 8);
	_cr->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  /// Read from the mb cache into the Cr img block .
  _cr8x8->Read(*(_cr));

  return(1);
}//end Restore.

/** Test if the cache is equal to the image block.
@param  pMb : Mb position to compare.
@return     : 1 = Equal, 0 = Not equal.
*/
int H264MbImgCache::Equal(MacroBlockH264* pMb)
{
  int lumEqual  = 0;
  int cbEqual   = 0;
  int crEqual   = 0;

  /// Align the Lum img block with this mb position
	_lum->SetOverlayDim(16, 16);
	_lum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
  lumEqual = _lum16x16->Equals(*(_lum));
  
  /// Align the Cb img block with this mb position
	_cb->SetOverlayDim(8, 8);
	_cb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  cbEqual = _cb8x8->Equals(*(_cb));

  /// Align the Cr img block with this mb position
	_cr->SetOverlayDim(8, 8);
	_cr->SetOrigin(pMb->_offChrX, pMb->_offChrY);
  crEqual = _cr8x8->Equals(*(_cr));

  return(lumEqual & cbEqual & crEqual);
}//end Equal.
========== END FILE: CodecUtils/H264MbImgCache.cpp ==========

========== BEGIN FILE: CodecUtils/H264MbImgCache.h ==========
Bundle entry: 57
Original bytes: 4538
Original SHA-256: 01454164841c5144ffcbbac56f8a713b861aa55834bc3aa6fc344811f35d3330
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264MbImgCache

TAG						: H264MIC

FILE NAME			: H264MbImgCache.h

DESCRIPTION		: A class to cache image blocks aligned with H.264 macroblocks data.

COPYRIGHT			:	(c)CSIR 2007-2014 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _H264MBIMGCACHE_H
#define _H264MBIMGCACHE_H

#pragma once

#include "OverlayMem2Dv2.h"
#include "MacroBlockH264.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class H264MbImgCache
{
public:
	H264MbImgCache(void);
	virtual ~H264MbImgCache(void);

/// Cache operations.
public:
	/** Create mem container.
	Set the mem for a 16x16 lum and two 8x8 chr blocks with their overlays.
	@return			: 1 = success, 0 = failed.
	*/
	int Create(void);

	/** Set the image space to operate on.
	Hold references to the image overlays that the mb will aligned with. This
  is done once and then all calls to Cache() or Restore() will reference this
  image.
  @param  lum : Lum overlay reference.
  @param  cb  : Chr Cb overlay reference.
  @param  cr  : Chr Cr overlay reference.
	@return			: 1 = success, 0 = failed.
	*/
  void SetImage(OverlayMem2Dv2* lum, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr)
  {
    _lum = lum; _cb = cb; _cr = cr; 
  }//end SetImage.

	/** Cache the mb aligned image.
	Use the mb data to align the mb with the image position and copy the image
  data into the cache.
  image.
  @param  pMb : Mb to cache.
	@return			: 1 = success, 0 = failed.
	*/
  int Cache(MacroBlockH264* pMb);

	/** Restore the mb aligned image from the cache.
	Use the mb data to align the mb with the image position and copy the cache
  data into the image.
  image.
  @param  pMb : Mb to restore.
	@return			: 1 = success, 0 = failed.
	*/
  int Restore(MacroBlockH264* pMb);

  /** Test if the cache is equal to the image block.
  @param  pMb : Mb position to compare.
  @return     : 1 = Equal, 0 = Not equal.
  */
  int Equal(MacroBlockH264* pMb);

/// Member access.
public:
	OverlayMem2Dv2*	GetLumCache(void)		{ return(_lum16x16); }
	OverlayMem2Dv2*	GetCbCache(void)		{ return(_cb8x8); }
	OverlayMem2Dv2*	GetCrCache(void)		{ return(_cr8x8); }

/// Private methods.
protected:
  void Destroy(void);

/// Private data block members.
protected:
  /// Image references.
  OverlayMem2Dv2* _lum;
  OverlayMem2Dv2* _cb;
  OverlayMem2Dv2* _cr;

  /// Cache blocks and overlays.
  short*          _plumCache;
  OverlayMem2Dv2* _lum16x16;
  short*          _pCbCache;
  OverlayMem2Dv2* _cb8x8;
  short*          _pCrCache;
  OverlayMem2Dv2* _cr8x8;

};// end class H264MbImgCache.

#endif	//_H264MBIMGCACHE_H
========== END FILE: CodecUtils/H264MbImgCache.h ==========

========== BEGIN FILE: CodecUtils/H264MotionVectorPredictorImpl1.h ==========
Bundle entry: 58
Original bytes: 4279
Original SHA-256: 0525b4418d94e690f820da069bf7d098585418f8975a6954956c791211fcedc9
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264MotionVectorPredictorImpl1

TAG						: H264MVPI1

FILE NAME			: H264MotionVectorPredictorImpl1.h

DESCRIPTION		: A class to predicting motion vectors from the surrounding motion
                vectors of previously encoded/decoded macroblocks. Implements the 
                IMotionVectorPredictor() interface.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _H264MOTIONVECTORPREDICTORIMPL1_H
#define _H264MOTIONVECTORPREDICTORIMPL1_H

#include "IMotionVectorPredictor.h"
#include "MacroBlockH264.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class H264MotionVectorPredictorImpl1 : public IMotionVectorPredictor
{
/// Construction.
public:

  H264MotionVectorPredictorImpl1(MacroBlockH264* pMb) { _pMb = pMb; }

  virtual ~H264MotionVectorPredictorImpl1(void) {}

/// IMotionVectorPredictor Interface.
public:
  virtual int	Create(void) { return(1); }

	/** Get the 16x16 2-D prediction for the macroblock/block.
  A NULL pList implies that the mb motion vectors are already valid otherwise
  load them from the pList first. The neighbourhood must also be correct from
  prior calls.
	@param pList	: Input list of motion vectors.
	@param blk		: Macroblock/block number to get the prediction for.
  @param predX  : Output predicted X coordinate
  @param predY  : Output predicted Y coordinate
	@return	      :	1 = success, 0 = failure.
	*/
	int Get16x16Prediction(	void* pList, int blk, int* predX, int* predY)
  {
    if(_pMb == NULL)
      return(0);

    MacroBlockH264::GetMbMotionMedianPred( &(_pMb[blk]), predX, predY);
    return(1);
  }

	/** Force a 16x16 motion vector for the macroblock/block.
  Used to set up future predictions.
	@param blk	: Macroblock/block number to set.
  @param mvX  : X coordinate
  @param mvY  : Y coordinate
	@return	    :	none.
	*/
	void Set16x16MotionVector(int blk, int mvX, int mvY)
  {
    if(_pMb == NULL)
      return;

    _pMb[blk]._mvX[MacroBlockH264::_16x16] = mvX;
    _pMb[blk]._mvY[MacroBlockH264::_16x16] = mvY;
  }

/// Local methods.
protected:

/// Local members.
protected:

	// Parameters must remain const for the life time of this instantiation.
  MacroBlockH264* _pMb; ///< List of the active image mbs.

};//end H264MotionVectorPredictorImpl1.

#endif // !_H264MOTIONVECTORPREDICTORIMPL1_H

========== END FILE: CodecUtils/H264MotionVectorPredictorImpl1.h ==========

========== BEGIN FILE: CodecUtils/H264RawFileHandler.cpp ==========
Bundle entry: 59
Original bytes: 3849
Original SHA-256: 68296e81b03f8e15465db76ff4477514c373383f666426b54ded759d3751eadd
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264RawFileHandler

TAG						: H264RFH

FILE NAME			: H264RawFileHandler.cpp

DESCRIPTION		: A class to hold H.264 slice header data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <fstream>

#include "H264RawFileHandler.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
H264RawFileHandler::H264RawFileHandler(void)
{
}//end constructor.

H264RawFileHandler::~H264RawFileHandler(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Public interface methods.
---------------------------------------------------------------------------
*/
/** Get a ptr to the head of the next encoded unit.
Return the ptr and the length of the next encoded frame/unit
of data after the currPos.
@param length : Bytes in the encoded unit
@return       : Ptr to the head of the unit.
*/
void* H264RawFileHandler::GetNextUnit(int* unitLen)
{
  if(_pFile == NULL)
  {
    *unitLen = 0;
    return(NULL);
  }//end if _pFile...

  if(_currPos >= (_length-1)) ///< Wrap around the end.
    _currPos = 0;

  int unitPos = _currPos;     ///< This unit starts here.

  /// From the current pos count the bytes to the start of the next 00 00 00 01 H.264 start code.
  int len = 4;
  _currPos += 4;
  int found = 0;
  for(  ; (_currPos < _length)&&(!found); _currPos++, len++)
  {
    if( (_pFile[_currPos-3] == 0)&&(_pFile[_currPos-2] == 0)&&(_pFile[_currPos-1] == 0)&&(_pFile[_currPos] == 1) )
      found = 1;
  }//end for _currPos...
  if(found)
  {
    _currPos -= 4;
    len -= 4;
  }//end if found...

  *unitLen = len;
  return((void*)( &(_pFile[unitPos]) ));
}//end GetNextFrame.


========== END FILE: CodecUtils/H264RawFileHandler.cpp ==========

========== BEGIN FILE: CodecUtils/H264RawFileHandler.h ==========
Bundle entry: 60
Original bytes: 2627
Original SHA-256: 0525e9da9092433333ff0fe6207a321353596408bf9097bf6e4e917703377bf1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264RawFileHandler

TAG						: H264RFH

FILE NAME			: H264RawFileHandler.h

DESCRIPTION		: A class to hold read and write raw H.264 encoded data from and to
                a binary file.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _H264RAWFILEHANDLER_H
#define _H264RAWFILEHANDLER_H

#pragma once

#include "RawFileHandlerBase.h"
/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class H264RawFileHandler : public RawFileHandlerBase
{
public:
	H264RawFileHandler(void);
	virtual ~H264RawFileHandler(void);

/// Public interface.
public:

  void* GetNextUnit(int* unitLen);

};// end class H264RawFileHandler.

#endif	//_H264RAWFILEHANDLER_H
========== END FILE: CodecUtils/H264RawFileHandler.h ==========

========== BEGIN FILE: CodecUtils/IBitStreamReader.h ==========
Bundle entry: 61
Original bytes: 4400
Original SHA-256: fddcae1b1e663258b2380fb7eeba3e4e0452fdd3a2c3ebc15c3bb9110cdf09fe
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IBitStreamReader

TAG						: IBSR

FILE NAME			: IBitStreamReader.h

DESCRIPTION		: A IBitStreamReader interface as an abstract base class 
								to BitStreamReader implementations that operate on 
								bit streams. 

COPYRIGHT			: (c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _IBITSTREAMREADER_H
#define _IBITSTREAMREADER_H

#pragma once

class IBitStreamReader
{
public:
	virtual ~IBitStreamReader() {}

/// Interface implementation.
public:
	/** Read a single bit.
	Read from the current bit position in the stream.
	@return	: The bit [0,1].
	*/
	virtual int Read(void) = 0;

	/** Read bits from the stream.
	Read multiple bits from the current stream position.
	@param numBits	: No. of bits to read.
	@return					: The code.
	*/
	virtual int Read(int numBits) = 0;

	/** Peek bits in the stream.
	Read multiple bits from the specified stream position 
	without disturbing the current stream position.
	@param bitLoc		: Bit pos in stream.
	@param numBits	: No. of bits to read.
	@return					: The code.
	*/
	virtual int Peek(int bitLoc, int numBits) = 0;

	/** Set the stream to use.
	Set the pointer to write the bits to and its length in
	bits. Resets the current position to zero.
	@param stream		:	Byte stream pointer.
	@param bitSize	: Length in bits of the stream.
	@return					:	none.
	*/
	virtual void SetStream(void* stream, int bitSize) = 0;	

	/** Get the stream used.
	@return	:	stream pointer.
	*/
  virtual void* GetStream(void) = 0;
  
	/** Reset position.
	Reset the bit position to the front of the stream.
	@return	:	none.
	*/
	virtual void Reset(void) = 0;

	/** Seek to a position.
	Seek the desired bit position from the front of
	the stream.
	@param streamBitPos	: Position to set.
	@return							: Success = 1, Past the end = 0;
	*/
	virtual int Seek(int streamBitPos) = 0;

	/** Get the current position.
	@return	:	bit/byte position.
	*/
	virtual int GetStreamBitPos(void) = 0;
	virtual int GetStreamBytePos(void) = 0;

	/** Set/change the bit length of the stream.
	@param bitSize	: New size in bits.
	@return					: nooe.
	*/
	virtual void SetStreamBitSize(int bitSize) = 0;
	virtual int	 GetStreamBitSize(void) = 0;

	/** Get the remaining bits left on the stream.
	@return	: Bits left.
	*/
	virtual int GetStreamBitsRemaining(void) = 0;

	/** Copy the contents from another bitstream.
  @param pFrom  : Bitstream to copy from.
	@return	      : none.
	*/
  virtual void  Copy(IBitStreamReader* pFrom)  = 0;

};// end class IBitStreamReader.

#endif	// _IBITSTREAMREADER_H
========== END FILE: CodecUtils/IBitStreamReader.h ==========

========== BEGIN FILE: CodecUtils/IBitStreamWriter.h ==========
Bundle entry: 62
Original bytes: 4898
Original SHA-256: 2589169dd1ee9a54e5d3aecc4b4249e87d12a02cf81ab0271e2c1c16c6692584
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IBitStreamWriter

TAG						: IBSW

FILE NAME			: IBitStreamWriter.h

DESCRIPTION		: A IBitStreamWriter interface as an abstract base class 
								to BitStreamWriter implementations that operate on 
								bit streams. 

COPYRIGHT			: (c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _IBITSTREAMWRITER_H
#define _IBITSTREAMWRITER_H

#pragma once

class IBitStreamWriter
{
public:
	virtual ~IBitStreamWriter() {}

/// Interface implementation.
public:
	/** Write a single bit.
	Write to the current bit position into the stream.
	@param val	: Bit value to write.
	@return			: none.
	*/
	virtual void Write(int val) = 0;

	/** Write bits to the stream - 32 bits.
	Write multiple bits into the current stream position for 32 bit values.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	virtual void Write(int numBits, int val) = 0;

	/** Write bits to the stream - 64 bits.
	Write multiple bits into the current stream position for 64 bit values.
	@param numBits	: No. of bits to write.
	@param valH			: Upper 32 bit value to write.
	@param valL			: Lower 32 bit value to write.
	@return					: none.
	*/
  virtual void Write(int numBits, int valH, int valL) = 0;

	/** Poke bits to the stream.
	Write multiple bits from into the specified stream 
	position without disturbing the	current stream position.
	@param bitLoc		: Bit pos in stream.
	@param numBits	: No. of bits to write.
	@param val			: Bit value to write.
	@return					: none.
	*/
	virtual void Poke(int bitLoc, int numBits, int val) = 0;

	/** Set the stream to use.
	Set the pointer to write the bits to and its length in
	bits. Resets the current position to zero.
	@param stream		:	Byte stream pointer.
	@param bitSize	: Length in bits of the stream.
	@return					:	none.
	*/
	virtual void SetStream(void* stream, int bitSize) = 0;	

	/** Get the stream used.
	@return	:	stream pointer.
	*/
  virtual void* GetStream(void) = 0;
  
	/** Reset position.
	Reset the bit position to the front of the stream.
	@return	:	none.
	*/
	virtual void Reset(void) = 0;

	/** Seek to a position.
	Seek the desired bit position from the front of
	the stream.
	@param streamBitPos	: Position to set.
	@return							: Success = 1, Past the end = 0;
	*/
	virtual int Seek(int streamBitPos) = 0;

	/** Get the current position.
	@return	:	bit/byte position.
	*/
	virtual int GetStreamBitPos(void) = 0;
	virtual int GetStreamBytePos(void) = 0;

	/** Set/change the bit length of the stream.
	@param bitSize	: New size in bits.
	@return					: none.
	*/
	virtual void SetStreamBitSize(int bitSize) = 0;
	virtual int	 GetStreamBitSize(void) = 0;

	/** Get the remaining bits left on the stream.
	@return	: Bits left.
	*/
	virtual int GetStreamBitsRemaining(void) = 0;

	/** Copy the contents from another bitstream.
  @param pFrom  : Bitstream to copy from.
	@return	      : none.
	*/
  virtual void  Copy(IBitStreamWriter* pFrom)  = 0;

};// end class IBitStreamWriter.

#endif	// _IBITSTREAMWRITER_H
========== END FILE: CodecUtils/IBitStreamWriter.h ==========

========== BEGIN FILE: CodecUtils/ICodecInnerAccess.h ==========
Bundle entry: 63
Original bytes: 4105
Original SHA-256: 1275e982d42db82f1f9cf50ede75f922a8ebb7ff9576c71afb815278b6a858d6
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE: ICodecInnerAccess

TAG: ICIA

FILE NAME: ICodecInnerAccess.h

DESCRIPTION: 
A ICodecInnerAccess Interface as an optional base class 
to expose the inner members of all video and audio codecs.
The destructor is protected to prevent deletion	of the 
associated super class. NOTE: These methods should only
be called after an Open() call on the ICodecv2 interface.

REVISION HISTORY:	

COPYRIGHT: (c)CSIR 2007-2018 all rights resevered

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions 
are met:

* Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.
* Neither the name of the CSIR nor the names of its contributors may be used 
to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _ICODECINNERACCESS_H
#define _ICODECINNERACCESS_H

#pragma once

class ICodecInnerAccess
{
protected:
	virtual ~ICodecInnerAccess() {}

public:
	/** Codec member access.
	This is the primary method of Get/Set for all members and caters for
	all variants by using strings and list pointers. Care must be taken 
	when unicode strings are used. Typical usage:
		int		len;
		int*	pMember = (int *)Impl->GetMember((const char*)("macroblocks"), &len);
		if(pMember == NULL)
			errorStr = (char *)Impl->GetErrorStr();

	On acquiring a handle to the member, any changes made to it will be reflected
	in the next call to Code/Decode of the codec. Interferring with the members
	could have disasterous side effects so care must be taken.

	@param type			:	A string of the member required.
	@param length		:	The length of the member list returned.
	@return					: success = member pointer, NULL = no member exists with this name.
	*/
	virtual void* GetMember(const char* type, int* length) = 0;

	/** Get member names.
	After requesting a "members" type to get the total no. of accessible members
	then all the names may be referenced as a list.
	@param ordinal	: The list index.
	@param name			: String name.
	@param length		: The length of the string returned in name.
	@return					: none.
	*/
	virtual void GetMemberName(int ordinal, const char** name, int* length) = 0;

	/** Set codec member.
	This is the primary method of Get/Set for all member and caters for
	all variants by using strings. Care must be taken when unicode strings
	are used. Typical usage:
		int	width = some;
		if(!Impl->SetMember((char *)("width"), (void *)(&width));
			errorStr = (char *)Impl->GetErrorStr();

	@param type		:	A string name of the member to set.
	@param pValue	:	A reference to the value to set.
	@return				: 1 = success, 0 = no member exists with this name.
	*/
	virtual int SetMember(const char* type, void* pValue) = 0;

};// end class ICodecInnerAccess.

#endif	//_ICODECINNERACCESS_H
========== END FILE: CodecUtils/ICodecInnerAccess.h ==========

========== BEGIN FILE: CodecUtils/ICodecv2.h ==========
Bundle entry: 64
Original bytes: 5930
Original SHA-256: dd07acc11910ea816de62991ca73df93cb90bfac9c30998c483cb0bba24febb2
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: ICodecv2

TAG						: ICV2

FILE NAME			: ICodecv2.h

DESCRIPTION		: A ICodecv2 Interface as an abstract base class to all 
								video	and audio codecs.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _ICODECV2_H
#define _ICODECV2_H

#pragma once

class ICodecv2
{
public:
	virtual ~ICodecv2() {}

	/** Codec parameter access.
	This is the primary method of Get/Set for all parameters and caters for
	all variants by using strings. Care must be taken when unicode strings
	are used. Typical usage:
		char		valBuff[20];
		int			len;
		if(!Impl->GetParameter((const char*)("width"), &len, (void *)valBuff))
			errorStr = (char *)Impl->GetErrorStr();

	@param type		:	A string of the parameter required.
	@param length	:	The length of the string returned in value.
	@param value	:	A string representing the value required.
	@return				: 1 = success, 0 = no parameter exists with this name.
	*/
	virtual int GetParameter(const char* type, int* length, void* value) = 0;

	/** Get parameter names.
	After requesting a "parameters" parameter to get the total no. of parameters
	then all the names may be referenced as a list.
	@param ordinal	: The list index.
	@param name			: String name.
	@param length		: The length of the string returned in name.
	@return					: none.
	*/
	virtual void GetParameterName(int ordinal, const char** name, int* length) = 0;

	/** Set codec parameter.
	This is the primary method of Get/Set for all parameters and caters for
	all variants by using strings. Care must be taken when unicode strings
	are used. Typical usage:
		char		Buffer[20];
		int			width = some;
		if(!Impl->SetParameter((char *)("width"), (char *)_itoa(width,Buffer,10));
			errorStr = (char *)Impl->GetErrorStr();

	@param type		:	A string of the parameter required.
	@param value	:	A string representing the value required.
	@return				: 1 = success, 0 = no parameter exists with this name.
	*/
	virtual int SetParameter(const char* type, const char* value) = 0;

	/** Get the last error string.
	@return	: Error string reference.
	*/
	virtual char* GetErrorStr(void) = 0;
	
	/** The codec is ready.
	This is signaled when a successful Open() has occurred before a 
	Close() is called.
	@return	: 1 = Is ready, 0 = not ready.
	*/
	virtual int Ready(void) = 0;

	/** Get the coded bit length.
	This indicates the exact no. of bits/bytes in the coded stream.
	@return	: The length.
	*/
	virtual int GetCompressedBitLength(void) = 0;
	virtual int GetCompressedByteLength(void) = 0;

	/** Access the reference images.
	Get a untyped ptr to the reference list where refNum = 0 is the latest.
	@param refNum	: References back in time (current = 0).
	@return				: Ptr to the reference.
	*/
	virtual void* GetReference(int refNum) = 0;

	/** Restart the codec.
	Used to generate key frames/pages/packets that have no prior
	dependencies on previously coded frames. Resets any prediction
	loops.
	@return	: none.
	*/
	virtual void Restart(void) = 0;

	/** Open the codec.
	Codec is opened with the parameter set described by the result
	of several SetParameter() calls. Defaults must be appropriate.
	@return	: 1 = success, 0 = failure.
	*/
	virtual int Open(void) = 0;

	/** Close an opened codec.
	Clear all memory allocations and reset the parameters to defaults.
	@return	: 1 = success, 0 = failure.
	*/
	virtual int Close(void) = 0;
	
	/** Encode the source.
	@param pSrc						: Source reference whose type is implicitly defined.
	@param pCmp						: Dest of the encoding.
	@param codeParameter	: Codec dependent interpretation.
	@return								: 1 = success, 0 = failure.
	*/
	virtual int Code(void* pSrc, void* pCmp, int codeParameter) = 0;

	/** Decode to the dest.
	@param pCmp				: Source reference of the encoded stream.
	@param bitLength	: Bit length of the source pCmp.
	@param pDst				: Dest reference whose type is implicitly defined.
	@return						: 1 = success, 0 = failure.
	*/
	virtual int Decode(void* pCmp, int bitLength, void* pDst) = 0;

};// end class ICodecv2.

#endif	//_ICODECV2_H
========== END FILE: CodecUtils/ICodecv2.h ==========

========== BEGIN FILE: CodecUtils/IContextAwareRunLevelCodec.h ==========
Bundle entry: 65
Original bytes: 4246
Original SHA-256: a55e1d5936a017c9bee5cf2f4432e0800c300c55182d8fb53cdcaca32c5471b5
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IContextAwareRunLevelCodec

TAG						: ICARLC

FILE NAME			: IContextAwareRunLevelCodec.h

DESCRIPTION		: A IContextAwareRunLevelCodec interface as an abstract base 
								class (well, almost) to context-aware run-level implementations
								that promote decoupling from the implementation.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _ICONTEXTAWARERUNLEVELCODEC_H
#define _ICONTEXTAWARERUNLEVELCODEC_H

#pragma once

class IContextAwareRunLevelCodec
{
public:
	virtual ~IContextAwareRunLevelCodec() {}

	/** Encode the input to a run-level bit stream.
	The input and output structs are implementation	specific and therefore
	undefined in the interface.
	@param in			:	Input list to encode.
	@param stream	:	Run-level encoded stream.
	@return				: Implementation specific return code.
	*/
	virtual int Encode(void* in, void* stream) = 0;

	/** Decode a run-level bit stream to the output.
	The input and output structs are implementation specific and therefore
	undefined in the interface.
	@param stream	:	Run-level stream to decode.
	@param out		:	Output list generated by the decode.
	@return				: Implementation specific return code.
	*/
	virtual int Decode(void* stream, void* out) = 0;

	/** Set and get the mode for the implementation.
	Implementations require some flexibility in the interface	to provide extra
	modes of operation that are internal. Most implementations will have empty 
	methods.
	@param mode	: Mode to set.
	@return			: None (Set) or the mode (Get).
	*/
	virtual void	SetMode(int mode) = 0;
	virtual int		GetMode(void) = 0;

	/** Set and get parameters for the implementation.
	Implementations require some flexibility in the interface	to provide extra
	parameters that are internal. Most implementations will have empty methods.
	@param paramID	: Parameter to set/get.
	@param paramVal	: Parameter value.
	@return					: None (Set) or the param value (Get).
	*/
	virtual void	SetParameter(int paramID, int paramVal) = 0;
	virtual int		GetParameter(int paramID) = 0;

public:
	/// Modes available.
	static const int Mode2x2 = 0;
	static const int Mode4x4 = 1;
	static const int Mode8x8 = 2;

	/// Parameter IDs.
	static const int NUM_TOT_NEIGHBOR_COEFF_ID	= 0;
	static const int DC_SKIP_FLAG_ID						= 1;
	static const int NUM_TOT_COEFF_ID						= 2;

};// end class IContextAwareRunLevelCodec.

#endif	//_ICONTEXTAWARERUNLEVELCODEC_H
========== END FILE: CodecUtils/IContextAwareRunLevelCodec.h ==========

========== BEGIN FILE: CodecUtils/IForwardDct.h ==========
Bundle entry: 66
Original bytes: 1572
Original SHA-256: 0cf9cd1f2322d83870c8628b971c74d5b6d5031a02545b6dba814666fff2983f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE						: IForwardDct

TAG								: IFD

FILE NAME					: IForwardDct.h

DESCRIPTION				: An interface to forward Dct implementations. The interface
										has 2 options as either in-place or from an input to an
										output parameter argument. The implementations must define
										the mem type (e.g. short, int) and whether it is a 2-D dct
										on a block or 1-D on an array.

REVISION HISTORY	:	

COPYRIGHT					: (c)CSIR, Meraka Institute 2007-2009 all rights resevered

RESTRICTIONS			: The information/data/code contained within this file is 
										the property of CSIR and is released under the OPEN BSD
										license.
===========================================================================
*/
#ifndef _IFORWARDDCT_H
#define _IFORWARDDCT_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IForwardDct
{
	public:
		virtual ~IForwardDct() {}
		
		/** In-place forward Dct.
		The Dct is performed on the input and replaces it with the coeffs.
		@param ptr	: Data to transform.
		@return			:	none.
		*/
		virtual void dct(void* ptr) = 0;

		/** Transfer forward Dct.
		The Dct is performed on the input and the coeffs are written to 
		the output.
		@param pIn		: Input data.
		@param pCoeff	: Output coeffs.
		@return				:	none.
		*/
		virtual void dct(void* pIn, void* pCoeff) = 0;

};//end IForwardDct.


#endif	// _IFORWARDDCT_H
========== END FILE: CodecUtils/IForwardDct.h ==========

========== BEGIN FILE: CodecUtils/IForwardTransform.h ==========
Bundle entry: 67
Original bytes: 4926
Original SHA-256: 4dbfa8a0fb71295da42d1060393f25954d8542127aedb72f2acbfc182e5a0c99
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IForwardTransform

TAG						: IFT

FILE NAME			: IForwardTransform.h

DESCRIPTION		: An interface to forward transform implementations. The 
								interface has 2 options as either in-place or from an 
								input to an output parameter argument. Further, they 
								may include or exclude the quantisation and scaling. 
								The implementations must define the mem type (e.g. short, 
								int) and whether it is a 2-D on a block or 1-D on an 
								array.

COPYRIGHT			:	(c)CSIR 2007-2014 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifndef _IFORWARDTRANSFORM_H
#define _IFORWARDTRANSFORM_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IForwardTransform
{
public:
	virtual ~IForwardTransform() {}
	
	/** In-place forward transform.
	The transform is performed on the input and replaces it with the coeffs.
	@param ptr	: Data to transform.
	@return			:	none.
	*/
	virtual void Transform(void* ptr) = 0;

	/** Transfer forward transform.
	The transform is performed on the input and the coeffs are written to 
	the output.
	@param pIn		: Input data.
	@param pCoeff	: Output coeffs.
	@return				:	none.
	*/
	virtual void Transform(void* pIn, void* pCoeff) = 0;

	/** Set scaling array.
	Each coefficient may be scaled after transforming and therefore 
	requires setting up.
	@param	pScale:	Scale factor array.
	@return				:	none.
	*/
	virtual void	SetScale(void* pScale) = 0;
	virtual void* GetScale(void) = 0;

	/** Set the mode of operation.
	Allow an implementation to define modes of operation or
	interpretation of the quantisation process.
	@param mode	: Mode to set.
	@return			: none.
	*/
	virtual void SetMode(int mode) = 0;
	virtual int  GetMode(void) = 0;

	/** Set and get parameters for the implementation.
	Implementations require some flexibility in the interface	to provide extra
	parameters that are internal. Most implementations will have empty methods.
	@param paramID	: Parameter to set/get.
	@param paramVal	: Parameter value.
	@return					: None (Set) or the param value (Get).
	*/
	virtual void	SetParameter(int paramID, int paramVal) = 0;
	virtual int		GetParameter(int paramID) = 0;

  /** Quantise a single value in a block.
  Implement quantising a value in a specified position of the coeffs at a
  specified QP value.
  @param val  : Value to quantise.
  @param pos  : Postion of value in 1-D array of 2-D data.
  @param qp   : Quant param to use.
  @return     : Result of quantisation.
  */
  virtual int QuantiseValue(short val, int pos, int qp) = 0;

	/// Global constants for all implementations.
public:

	/// Parameter IDs.
	static const int QUANT_ID						= 0;	///< Sets/Gets quantisation parameter.
	static const int INTRA_FLAG_ID			= 1;	///< Sets/Gets intra flag.

	/// Modes.
	static const int TransformAndQuant	= 0;
	static const int TransformOnly			= 1;
	static const int QuantOnly					= 2;

};//end IForwardTransform.


#endif	// _IFORWARDTRANSFORM_H
========== END FILE: CodecUtils/IForwardTransform.h ==========

========== BEGIN FILE: CodecUtils/IInverseTransform.h ==========
Bundle entry: 68
Original bytes: 4465
Original SHA-256: 3ff6e44039d8bea3b61ac00899d492b7e8a987e72305b4c8075b409aa36ed754
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IInverseTransform

TAG						: IIT

FILE NAME			: IInverseTransform.h

DESCRIPTION		: An interface to inverse transform implementations. The 
								interface has 2 options as either in-place or from an 
								input to an output parameter argument. Further, they 
								may include or exclude the quantisation. The 
								implementations must define the mem type (e.g. short, 
								int) and whether it is a 2-D on a block or 1-D on an 
								array.

COPYRIGHT			:	(c)CSIR 2007-2009 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

============================================================================================
*/
#ifndef _IINVERSETRANSFORM_H
#define _IINVERSETRANSFORM_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IInverseTransform
{
public:
	virtual ~IInverseTransform() {}
	
	/** In-place inverse Dct.
	The inverse Dct is performed on the input and replaces it with the coeffs.
	@param p	: Data to transform.
	@return		:	none.
	*/
	virtual void InverseTransform(void* ptr) = 0;

	/** Transfer inverse Dct.
	The inverse Dct is performed on the coeffs and are written to 
	the output.
	@param pCoeff	: Input coeffs.
	@param pOut		: Output data.
	@return				:	none.
	*/
	virtual void InverseTransform(void* pCoeff, void* pOut) = 0;

	/** Set scaling array.
	Each coefficient may be scaled before transforming and therefore 
	requires setting up.
	@param	pScale:	Scale factor array.
	@return				:	none.
	*/
	virtual void	SetScale(void* pScale) = 0;
	virtual void* GetScale(void) = 0;

	/** Set the mode of operation.
	Allow an implementation to define modes of operation or
	interpretation of the quantisation process.
	@param mode	: Mode to set.
	@return			: none.
	*/
	virtual void SetMode(int mode) = 0;
	virtual int  GetMode(void) = 0;

	/** Set and get parameters for the implementation.
	Implementations require some flexibility in the interface	to provide extra
	parameters that are internal. Most implementations will have empty methods.
	@param paramID	: Parameter to set/get.
	@param paramVal	: Parameter value.
	@return					: None (Set) or the param value (Get).
	*/
	virtual void	SetParameter(int paramID, int paramVal) = 0;
	virtual int		GetParameter(int paramID) = 0;

	/// Global constants for all implementations.
public:

	/// Parameter IDs.
	static const int QUANT_ID						= 0;	///< Sets/Gets quantisation parameter.

	/// Modes.
	static const int TransformAndQuant	= 0;
	static const int TransformOnly			= 1;
	static const int QuantOnly					= 2;

};//end IInverseTransform.


#endif	// _IINVERSETRANSFORM_H
========== END FILE: CodecUtils/IInverseTransform.h ==========

========== BEGIN FILE: CodecUtils/IMotionCompensator.h ==========
Bundle entry: 69
Original bytes: 5082
Original SHA-256: dd46a7090a8531fd701782bdb5c236b18f25a4a9b09281885ec7d226dfcfbc30
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE						: IMotionCompensator

TAG								: IMC

FILE NAME					: IMotionCompensator.h

DESCRIPTION				: An interface to motion compensator implementations. 
										VectorList objects are compensated to a YUV420
										image ref.

REVISION HISTORY	:	25/09/2006 (KF): A single vector mode was added to
										the interface to allow one vector at a time to be 
										compensated. This requires an overload for the
										Compensate() method and a new method PrepareForSingleVectorMode()
										for dumping the ref into temp before compensating.

										29/09/2006 (KF): Removed the reference to VectorList objects
										to allow any structured object in the interface. The
										implementations will now define the list structure.

COPYRIGHT			: (c)CSIR 2007-2018 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _IMOTIONCOMPENSATOR_H
#define _IMOTIONCOMPENSATOR_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IMotionCompensator
{
	public:
		virtual ~IMotionCompensator() {}
		
		/** Create any private memory required.
		This is primarily to encourage a two stage construction process where
		mem is not alloc in the implementation constructor. The ref points to
		contiguous mem of Lum[imgHeight*imgWidth] followed by ChrU and then ChrV
		at half the image dimensions for YUV420 planar representation.
		@return	:	1 = success, 0 = failure.
		*/
		virtual int Create(void* ref, int imgWidth,				int imgHeight, 
																	int macroBlkWidth,	int macroBlkHeight) = 0;

		/** Destroy any private mem allocations.
		Mem is dealloc without changing the size parameters.
		@return	:	none.
		*/
		virtual void Destroy(void) = 0;

		/** Reset any previous frame assumptions.
		But do not change any	mem variables or delete anything.
		@return	: none.
		*/
		virtual void Reset(void) = 0;

		/** Motion compensate to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create().
		@param pMotionList	: The list of motion vectors.
		@return							: None.
		*/
		virtual void Compensate(void* pMotionList) = 0;

		/** Motion compensate a single vector to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create(). PrepareForSingleVectorMode()
		should be called once per compensation session before this method.
		@param tlx	: Top left x coord of block.
		@param tly	: Top left y coord of block.
		@param mvx	: X coord of the motion vector.
		@param mvy	: Y coord of the motion vector.
		@return			: None.
		*/
		virtual void Compensate(int tlx, int tly, int mvx, int mvy) = 0;
		
		/** Prepare the ref for single motion vector compensation mode.
		Should be used to copy the ref into a temp location from which to
		do the compensation to the ref. Prevents interference and double
		compensation. Use the Invalidate() command to force compensation
    on a vector by vector basis.
		@return : none.
		*/
		virtual void PrepareForSingleVectorMode(void) = 0;
    virtual void Invalidate(void) {}

};//end IMotionEstimator.


#endif
========== END FILE: CodecUtils/IMotionCompensator.h ==========

========== BEGIN FILE: CodecUtils/IMotionEstimator.h ==========
Bundle entry: 70
Original bytes: 3845
Original SHA-256: 2b5bb22b21f93d24b78533211a3c29dd526d025e2945d595e8edf29ec7d8bd96
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IMotionEstimator

TAG						: IME

FILE NAME			: IMotionEstimator.h

DESCRIPTION		: An interface to motion estimator implementations. Results
								are generated as a VectorList object.

COPYRIGHT			: (c)CSIR 2007-2018 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _IMOTIONESTIMATOR_H
#define _IMOTIONESTIMATOR_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IMotionEstimator
{
	public:
		virtual ~IMotionEstimator() {}
		
		/** Create any private memory required.
		This is primarily to encourage a two stage construction process where
		mem is not alloc in the implementation constructor.
		@return	:	1 = success, 0 = failure.
		*/
		virtual int Create(void) = 0;

		/** Reset any previous frame assumptions.
		But do not change any	mem variables or delete anything.
		@return	: none.
		*/
		virtual void Reset(void) = 0;

		/** Ready to estimate.
		Was the implementation correctly constructed and ready to estimate.
		@return	: 1 = yes, 0 = no.
		*/
		virtual int Ready(void) = 0;

		/** Set decision modes.
		These modes are defined by the implementation and are typically 
		compromises between speed and accuracy.
		@param mode	:	Mode to set. default (0 = auto).
		*/
		virtual void	SetMode(int mode) = 0;
		virtual int		GetMode(void) = 0;

		/** Motion estimate the source within the reference.
		Do the estimation with the block sizes and image sizes defined in
		the implementation. The returned type holds the vectors.
		@param pSrc		: Input image to estimate.
		@param pRef		: Ref to estimate with.
		@return				: The list of motion vectors.
		*/
		virtual void* Estimate(	const void* pSrc, 
														const void* pRef,
														long* avgDistortion) = 0;
		virtual void* Estimate(long* avgDistortion) = 0;
    virtual void* Estimate(long* avgDistortion, void* param) { return(Estimate(avgDistortion)); }

};//end IMotionEstimator.


#endif
========== END FILE: CodecUtils/IMotionEstimator.h ==========

========== BEGIN FILE: CodecUtils/IMotionVectorPredictor.h ==========
Bundle entry: 71
Original bytes: 3555
Original SHA-256: f6dd3853247127ad3f711dd81a2ed8f974f527bc24695e84c32da36caf97a66f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IMotionVectorPredictor

TAG						: IMVP

FILE NAME			: IMotionVectorPredictor.h

DESCRIPTION		: An interface to class implementations that predict the motion
                vector for the current macroblock/block from the surrounding
                previously encoded/decoded motion vectors. 

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _IMOTIONVECTORPREDICTOR_H
#define _IMOTIONVECTORPREDICTOR_H

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IMotionVectorPredictor
{
	public:
		virtual ~IMotionVectorPredictor() {}
		
		/** Create any private memory required.
		This is primarily to encourage a two stage construction process where
		mem is not alloc in the implementation constructor.
		@return	:	1 = success, 0 = failure.
		*/
		virtual int Create(void) = 0;

		/** Get the 16x16 2-D prediction for the macroblock/block.
		@param pList	: Input list of motion vectors.
		@param blk		: Macroblock/block number to get the prediction for.
    @param predX  : Output predicted X coordinate
    @param predX  : Output predicted Y coordinate
		@return	      :	1 = success, 0 = failure.
		*/
		virtual int Get16x16Prediction(	void* pList, int blk, int* predX, int* predY) = 0;

	  /** Force a 16x16 motion vector for the macroblock/block.
    Used to set up future predictions.
	  @param blk	: Macroblock/block number to set.
    @param mvX  : X coordinate
    @param mvY  : Y coordinate
	  @return	    :	none.
	  */
    virtual void Set16x16MotionVector(int blk, int mvX, int mvY) {}

};//end IMotionVectorPredictor.

#endif  /// _IMOTIONVECTORPREDICTOR_H
========== END FILE: CodecUtils/IMotionVectorPredictor.h ==========

========== BEGIN FILE: CodecUtils/IRateControl.h ==========
Bundle entry: 72
Original bytes: 5422
Original SHA-256: 89c9e5ce14dd623184af2838fc461ee73b7268231fa6e1f83f30e4805230f64c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IRateControl

TAG						: IRC

FILE NAME			: IRateControl.h

DESCRIPTION		: An interface to rate control implementations.

COPYRIGHT			:	(c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifndef _IRATECONTROL_H
#define _IRATECONTROL_H

#pragma once

#include  "GeneralUtils/Fifo.h"

/*
---------------------------------------------------------------------------
	Interface definition.
---------------------------------------------------------------------------
*/
class IRateControl
{
public:
	virtual ~IRateControl() {}
	
  virtual int		Create(int numOfFrames) = 0;
  virtual void	Destroy(void) = 0;
  virtual int   GetFameBufferLength(void) = 0;
  virtual void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) = 0;

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target rate.
  virtual int PredictDistortion(double targetAvgRate, double rateLimit) = 0;

  /// Post-encoding: Add sample measurements to the buffer/s and update the model parameters.
  virtual void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae) = 0;

  /// Return a performance measure that is implementation specific.
  virtual double GetPerformanceMeasure(void) = 0;

  /// Are the data in the buffers valid?
  virtual int ValidData(void) = 0;
    
  /// Was the prediction calculation out of bounds?
  virtual bool OutOfBounds(void) = 0;
  /// Who is the culprit?
  virtual bool UpperDistortionOverflow(void)  { return(false); }
  virtual bool LowerDistortionOverflow(void)  { return(false); }
  virtual bool UpperRateOverflow(void)        { return(false); }
  virtual bool LowerRateOverflow(void)        { return(false); }

  /// Reset the buffer to invalid with option to preset buffers.
  virtual void Reset(void) = 0;

  /// Intervensions to normal operation.
  virtual void SignalSceneChange(double mse, double mae) {}

  /// Utility function for testing and research data collection.
  virtual void Dump(const char* filename) = 0;
  virtual void Dump(void) { } ///< Optional internal filename dump.

  /// Commonly used utility methods (code refactoring)
protected:
  /// For running sums of a buffer. Adding the new value and dropping the oldest previous value.
  virtual double UpdateRunningSum(double prev, double curr, double currSum) { double newSum = currSum - prev; newSum += curr; return(newSum); }

  /// Solve in 2 variables returning soln in (x0, x1). If the determinant = 0 then leave (x0, x1) unchanged.
  virtual void CramersRuleSoln(double a00, double a01, double a10, double a11, double b0, double b1, double* x0, double* x1)
  { double D = (a00 * a11)-(a10 * a01);
    if(D != 0.0) { *x0 = ((b0 * a11)-(b1 * a01))/D; *x1 = ((a00 * b1)-(a10 * b0))/D; }  }

  /// Add to a fifo and store value that drops off the end of the fifo. Options for storing the log of the value or not.
  virtual void PutLogMeasure(Fifo& samples, double m, double* prev, bool initialise)
  { if (m <= 0.0) m = 0.0001; if (!initialise) *prev = samples.GetFirstOut(); else *prev = log(m); samples.AddFirstIn(log(m)); }
  virtual void PutLinearMeasure(Fifo& samples, double m, double* prev, bool initialise)
  { if (!initialise) *prev = samples.GetFirstOut(); else *prev = m; samples.AddFirstIn(m); }

  /// Model equations.
  virtual double ModelDistortion(double rate, double a, double b, double var) { return(0.0); }
  virtual double ModelRate(double distortion, double a, double b, double var) { return(0.0); }

};//end IRateControl.


#endif	// _IRATECONTROL_H
========== END FILE: CodecUtils/IRateControl.h ==========

========== BEGIN FILE: CodecUtils/IRunLengthCodec.h ==========
Bundle entry: 73
Original bytes: 1829
Original SHA-256: dd9fb61a797dff66586b90d0beb3aeac5432b1bdbf24d20168f484250d28e8c4
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE						: IRunLengthCodec

TAG								: IRLC

FILE NAME					: IRunLengthCodec.h

DESCRIPTION				: A IRunLengthCodec interface as an abstract base class 
										to run-length implementations that promote decoupling 
										of the implementation. 

REVISION HISTORY	:

COPYRIGHT					:	(c)CSIR 2007-2009 all rights resevered

RESTRICTIONS			: The information/data/code contained within this file is 
										the property of CSIR and is released under the OPEN BSD
										license.
===========================================================================
*/
#ifndef _IRUNLENGTHCODEC_H
#define _IRUNLENGTHCODEC_H

#pragma once

class IRunLengthCodec
{
public:
	virtual ~IRunLengthCodec() {}

	/** Encode the input to a run-length structure.
	The input and output rle struct are implementation
	specific and therefore undefined in the interface.
	@param in		:	Input list to encode.
	@param rle	:	Run-length struct generated by the encode.
	@return			: none.
	*/
	virtual void Encode(void* in, void* rle) = 0;

	/** Decode a run-length struct to the output.
	The input rle struct and output are implementation
	specific and therefore undefined in the interface.
	@param rle	:	Run-length struct to decode.
	@param out	:	Output list generated by the decode.
	@return			: none.
	*/
	virtual void Decode(void* rle, void* out) = 0;

	/** Set and get the mode for the implementation.
	Implementations require some flexibility in the interface
	to provide extra modes of operation that are internal. Most
	implementations will have empty methods.
	@param mode	: Mode to set.
	@return			: None (Set) or the mode (Get).
	*/
	virtual void SetMode(int mode) = 0;
	virtual int GetMode(void) = 0;

};// end class IRunLengthCodec.

#endif	//_IRUNLENGTHCODEC_H
========== END FILE: CodecUtils/IRunLengthCodec.h ==========

========== BEGIN FILE: CodecUtils/IStreamHeaderReader.h ==========
Bundle entry: 74
Original bytes: 3476
Original SHA-256: f35cfedd1139853a268f2d42c2b807d89369741c2eeb17a3f97b0603ac2a967e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE						: IStreamHeaderReader

TAG								: ISHR

FILE NAME					: IStreamHeaderReader.h

DESCRIPTION				: An IStreamHeaderReader Interface is an abstract base class 
										to access stream headers that have bit representations. 
										The access is defined by text (ASCII) strings. Derived 
										classes should include members for each header parameter
										and an associated Get() method.

COPYRIGHT			: (c)CSIR 2007-2018 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _ISTREAMHEADERREADER_H
#define _ISTREAMHEADERREADER_H

#pragma once

class IStreamHeaderReader
{
public:
	virtual ~IStreamHeaderReader() {}

	/** Extract the header from the input stream.
	Extract the header from the input stream into the derived
	class members.
	@param pSS		: Stream to extract from.
	@param bitLen	: Bit length of input stream.
	@return				: 1 = success, 0 = failed.
	*/
	virtual int Extract(void* pSS, int bitLen) = 0;

  /** Get the header length in bits.
  @return : Length in bits.
  */
	virtual int GetHeaderBitLength(void) = 0;

	/** Get the header value by name.
	This is the primary method of getting all header variables and caters 
	for all variants by using strings. Care must be taken when unicode strings
	are used. Typical usage:
		int	val;
		if( !Impl->Get((const unsigned char*)("width"), &val) )
			errorStr = "Header value does not exist";

	@param name		:	A string of the header variable required.
	@param value	:	The header value required.
	@return				: 1 = found, 0 = no header exists with this name.
	*/
	virtual int Get(const char* name, int* value) = 0;

};// end class IStreamHeaderReader.

#endif	///<_ISTREAMHEADERREADER_H
========== END FILE: CodecUtils/IStreamHeaderReader.h ==========

========== BEGIN FILE: CodecUtils/IVlcDecoder.h ==========
Bundle entry: 75
Original bytes: 3953
Original SHA-256: 41cee3c5149a38e90fa5e9bc31c4302df84d3f487b95d873ec643633b463f735
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IVlcDecoder

TAG						: IVD

FILE NAME			: IVlcDecoder.h

DESCRIPTION		: A IVlcDecoder Interface as an abstract base class. This
								is not all pure virtual and has an extended interface 
								with trivial default implementations.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
===========================================================================
*/
#ifndef _IVLCDECODER_H
#define _IVLCDECODER_H

#include "IBitStreamReader.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/

class IVlcDecoder
{
public:
	virtual ~IVlcDecoder() { }

	/*
	--------------------------------------------------------------------------
	Interface implementation.
	--------------------------------------------------------------------------
	*/
	/** Get the number of decoded bits from the last Decode().
	@return	: Total num bits extracted from the bit stream.
	*/
	virtual int GetNumDecodedBits(void)				= 0;

	/** Is it a marker code.
	Test if the last symbol returned from Decode() was a 
	marker code.
	@return	: 0 = not a marker, 1 = is a marker.
	*/
	virtual int Marker(void)									= 0;

	/** Decode the next symbol from the bit stream.
	Extra info associated with the extraction are stored in 
	the state members that may be accessed after this call.
	e.g. Marker(), GetNumDecodedBits(), etc.
	@param bsr	: Bit stream to read from.
	@return			: The next symbol.
	*/
	virtual int Decode(IBitStreamReader* bsr)	= 0;

	/*
	--------------------------------------------------------------------------
	Optional interface implementation.
	--------------------------------------------------------------------------
	*/
	virtual int		Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)									{return(0);}
	virtual int		Decode3(IBitStreamReader* bsr, int* symbol1, int* symbol2, int* symbol3)		{return(0);}
	virtual int		Decode3(int numBits, int codeword, int* symbol1, int* symbol2, int* symbol3){return(0);}
	virtual void	SetEsc(int numEscBits, int escMask)																					{ }

};// end class IVlcDecoder.

#endif	// _IVLCDECODER_H
========== END FILE: CodecUtils/IVlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/IVlcEncoder.h ==========
Bundle entry: 76
Original bytes: 3344
Original SHA-256: c51567c96350749a720254c6a51a415b9594a407c76db3d9724ca53df6ad5313
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: IVlcEncoder

TAG						: IVE

FILE NAME			: IVlcEncoder.h

DESCRIPTION		: A IVlcEncoder Interface as an abstract base class. The
								optional interface methods are not abstract but have
								trivial default implementations.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

========================================================================================
*/
#ifndef _IVLCENCODER_H
#define _IVLCENCODER_H

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class IVlcEncoder
{
public:
	virtual ~IVlcEncoder() { }

	/*
	--------------------------------------------------------------------------
	Interface implementation.
	--------------------------------------------------------------------------
	*/
	virtual int GetNumCodedBits(void)	= 0;
	virtual int GetCode(void)					= 0;
	virtual int Encode(int symbol)		= 0;

	/*
	--------------------------------------------------------------------------
	Optional interface implementation.
	--------------------------------------------------------------------------
	*/
	virtual int		Encode2(int symbol1, int symbol2)								{return(0);}
	virtual int		Encode3(int symbol1, int symbol2, int symbol3)	{return(0);}
	virtual void	SetEsc(int numEscBits, int escMask)							{ }
	virtual void	SetMode(int mode)																{ }
	virtual int		GetMode(void)																		{ return(0); }
  virtual int   GetExtCode(void)                                { return(0); }

};// end class IVlcEncoder.

#endif
========== END FILE: CodecUtils/IVlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/MacroBlockH264.cpp ==========
Bundle entry: 77
Original bytes: 48377
Original SHA-256: 008a4de0d407ac7f171b923692dd02989077290bc950560f9f34dc7e45fc7b73
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MacroBlockH264

TAG						: MBH264

FILE NAME			: MacroBlockH264.cpp

DESCRIPTION		: A class to hold H.264 macroblock specific data. Only static 
								methods that apply to macroblocks are used because it is 
								expected that there will be one MacroBlockH264() instantiation
								per overlay position on the picture.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <string.h>
#include "MacroBlockH264.h"
#include "GeneralUtils/MeasurementTable.h"
#include "OverlayMem2Dv2.h"

/// Macros
#include "CodecDistortionDef.h"

/// It is simpler to derive neighbourhoods of macroblocks if they are left in 
/// rater scanning order right up until their encodings are written onto the
/// bit stream. Therefore a coding order mapping is defined here to reorder
/// the final write as defined by H.264 standard.
const int MacroBlockH264::mbCodingOrderY[4][4] =
	{ { 0, 0, 1, 1 }, 
		{ 0, 0, 1, 1 }, 
		{ 2, 2, 3, 3 }, 
		{ 2, 2, 3, 3 } 
	};
const int MacroBlockH264::mbCodingOrderX[4][4] =
	{ { 0, 1, 0, 1 }, 
		{ 2, 3, 2, 3 }, 
		{ 0, 1, 0, 1 }, 
		{ 2, 3, 2, 3 } 
	};

/// The chr coeffs are less harshly quantised then the lum. This table is
/// the mapping structure as defined in ITU-T Rec. H.264 (03/2005) page 167
///	Table 8-15.
const int MacroBlockH264::QPltoQPcMap[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
	};

/// Macroblock types for I_Slices and Intra_16x16 prediction mode.
const int MacroBlockH264::Intra16x16ModeTable[24][3] =
	{ /// _intra16x16PredMode,  _codedBlkPatternChr, _codedBlkPatternLum
												{ 0,										0,										0 },	/// 1
												{ 1,										0,										0 },	/// 2
												{ 2,										0,										0 },	/// 3
												{ 3,										0,										0 },	/// 4
												{ 0,										1,										0 },	/// 5
												{ 1,										1,										0 },	/// 6
												{ 2,										1,										0 },	/// 7
												{ 3,										1,										0 },	/// 8
												{ 0,										2,										0 },	/// 9
												{ 1,										2,										0 },	/// 10
												{ 2,										2,										0 },	/// 11
												{ 3,										2,										0 },	/// 12
												{ 0,										0,									 15 },	/// 13
												{ 1,										0,									 15 },	/// 14
												{ 2,										0,									 15 },	/// 15
												{ 3,										0,									 15 },	/// 16
												{ 0,										1,									 15 },	/// 17
												{ 1,										1,									 15 },	/// 18
												{ 2,										1,									 15 },	/// 19
												{ 3,										1,									 15 },	/// 20
												{ 0,										2,									 15 },	/// 21
												{ 1,										2,									 15 },	/// 22
												{ 2,										2,									 15 },	/// 23
												{ 3,										2,									 15 } 	/// 24
	};

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
MacroBlockH264::MacroBlockH264(void)
{
	int i,j;

	/// Relative pixel coords (top left) of this macroblock in a contiguous image mem. Each
	/// block in the macroblock describes its relative position from this offset.
	_offLumX = 0;
	_offLumY = 0;
	_offChrX = 0;
	_offChrY = 0;
	_mbIndex = 0;	///< The index of this macroblock in the image space.
	_slice	 = 0;	///< Slice number that this macroblock belongs to.

	/// References to this macroblock's neighbours that will be used for the predictions.
	/// These are related to ITU-T Rec. H.264 (03/2005) page 27 Section 6.4.6 and will
	/// have a NULL value if they are not available. E.g. Top row macroblocks will have
	/// all the _aboveMbxxx = NULL.
	_leftMb				= NULL;		///< mbAddrA.
	_aboveLeftMb	= NULL;		///< mbAddrD.
	_aboveMb			= NULL;		///< mbAddrB.
	_aboveRightMb	= NULL;		///< mbAddrC.

	/// Macroblock quantisation parameter derived from delta qp values.
	_mbQP     = 1;
  _mbEncQP  = 1;  ///< QP used to store the _mbQP value that was used for the encoding.

	/// The macroblock type coded value mb_type is constructed from combinations 
	/// of the following modes.
	_intraFlag					= 1;							///< Indicates the macroblock Intra/Inter status.
	_mbPartPredMode			= Intra_16x16;		///< Macroblock partition prediction mode.
	_mbSubPartPredMode	= 0;							///< ...sub partition mode when partition mode is 8x8.
	_intra16x16PredMode	= Intra_16x16_DC;	///< Only for Intra_16x16 macroblocks.
	_intraChrPredMode		= Intra_Chr_DC;		///< For Intra_4x4 and Intra_16x16 macroblocks = {0..3}.
	_codedBlkPatternChr	= 0;
	_codedBlkPatternLum	= 0;

	/// Distortion-Rate optimisations require storing intermediate values. The arrays
	/// are directly addressable by _mbQP. Use an include flag to help with 
	/// heuristic elimination.
	_mvDistortion	= 0;		///< Total motion compensated distortion.
	_mvRate				= 0;		///< Total motion vector bit count.
	_include			= 1;
	for(i = 0; i < 52; i++)	///< mbQP = {0...51}
	{
		_distortion[i]	= 0;	
		_rate[i]				= 0;
	}//end for i...

	/// A flag to indicate that this macroblock has nothing to code and is skipped.
	_skip = 0;

	/// The macroblock type defines the partitioning, predictionmodes and the coded
	/// block patterns.
	_mb_type						= 1;
	_sub_mb_type				= 0;
	_coded_blk_pattern	= 0;

	/// Differential quantisation parameter for lum coeffs. Chr quant parameter is
	/// derived from the lum qp.
	_mb_qp_delta = 0;

	/// Motion Vectors and their differences. From 1 to 16 vectors depending the 
	/// partitions and sub partition sizes.
	for(i = 0; i < 16; i++)
	{
		_mvX[i]  = 0;
		_mvY[i]  = 0;
		_mvdX[i] = 0;
		_mvdY[i] = 0;
	}//end for i...

	/// The DC Chr blocks are instantiated as 4x4 and must reset
	/// to 2x2.
	_cbDcBlk.SetDim(2,2);
	_crDcBlk.SetDim(2,2);
	_cbDcBlkTmp.SetDim(2,2);
	_crDcBlkTmp.SetDim(2,2);

	/// Load the block parameter structure and the block types.
	/// Block num = -1 (Lum DC block);
	_blkParam[0].pBlk								= &_lumDcBlk;
	_blkParam[0].pBlkTmp						= &_lumDcBlkTmp;
	_blkParam[0].rasterIndex				= 0;
	_blkParam[0].dcSkipFlag					= 0;
	_blkParam[0].neighbourIndicator	= 1;
	_lumDcBlk.SetColour(BlockH264::LUM);
	_lumDcBlk.SetDcFlag(1);
	_lumDcBlkTmp.SetColour(BlockH264::LUM);
	_lumDcBlkTmp.SetDcFlag(1);
	///< 16 Lum blocks without DC value. Block num = 0..15
	int blkNum = 1;
	for(i = 0; i < 4; i++)	
		for(j = 0; j < 4; j++)	
		{
			int blkY = mbCodingOrderY[i][j];
			int blkX = mbCodingOrderX[i][j];
			_blkParam[blkNum].pBlk								= &(_lumBlk[blkY][blkX]);
			_blkParam[blkNum].pBlkTmp							= &(_lumBlkTmp[blkY][blkX]);
			_blkParam[blkNum].rasterIndex					= (4*blkY) + blkX;
			_blkParam[blkNum].dcSkipFlag					= 1;	///< Initialise assuming Intra macroblock.
			_blkParam[blkNum].neighbourIndicator	= 1;
			_lumBlk[blkY][blkX].SetColour(BlockH264::LUM);
			_lumBlk[blkY][blkX].SetDcFlag(0);
			_lumBlkTmp[blkY][blkX].SetColour(BlockH264::LUM);
			_lumBlkTmp[blkY][blkX].SetDcFlag(0);
			blkNum++;
		}//end for i & j...
	/// Chr DC next. Block num = 16 & 17.
	_blkParam[blkNum].pBlk								= &_cbDcBlk;
	_blkParam[blkNum].pBlkTmp							= &_cbDcBlkTmp;
	_blkParam[blkNum].rasterIndex					= 0;
	_blkParam[blkNum].dcSkipFlag					= 0;
	_blkParam[blkNum].neighbourIndicator	= -1;
	_cbDcBlk.SetColour(BlockH264::CB);
	_cbDcBlk.SetDcFlag(1);
	_cbDcBlkTmp.SetColour(BlockH264::CB);
	_cbDcBlkTmp.SetDcFlag(1);
	blkNum++;
	_blkParam[blkNum].pBlk								= &_crDcBlk;
	_blkParam[blkNum].pBlkTmp							= &_crDcBlkTmp;
	_blkParam[blkNum].rasterIndex					= 0;
	_blkParam[blkNum].dcSkipFlag					= 0;
	_blkParam[blkNum].neighbourIndicator	= -1;
	_crDcBlk.SetColour(BlockH264::CR);
	_crDcBlk.SetDcFlag(1);
	_crDcBlkTmp.SetColour(BlockH264::CR);
	_crDcBlkTmp.SetDcFlag(1);
	blkNum++;
	///< 4 Cb Chr blocks without DC value. Block num = 18..21
	for(i = 0; i < 2; i++)	
		for(j = 0; j < 2; j++)	
		{
			_blkParam[blkNum].pBlk								= &(_cbBlk[i][j]);
			_blkParam[blkNum].pBlkTmp							= &(_cbBlkTmp[i][j]);
			_blkParam[blkNum].rasterIndex					= (2*i) + j;
			_blkParam[blkNum].dcSkipFlag					= 1;
			_blkParam[blkNum].neighbourIndicator	= 1;
			_cbBlk[i][j].SetColour(BlockH264::CB);
			_cbBlk[i][j].SetDcFlag(0);
			_cbBlkTmp[i][j].SetColour(BlockH264::CB);
			_cbBlkTmp[i][j].SetDcFlag(0);
			blkNum++;
		}//end for i & j...
	///< 4 Cr Chr blocks without DC value. Block num = 22..25
	for(i = 0; i < 2; i++)	
		for(j = 0; j < 2; j++)	
		{
			_blkParam[blkNum].pBlk								= &(_crBlk[i][j]);
			_blkParam[blkNum].pBlkTmp							= &(_crBlkTmp[i][j]);
			_blkParam[blkNum].rasterIndex					= (2*i) + j;
			_blkParam[blkNum].dcSkipFlag					= 1;
			_blkParam[blkNum].neighbourIndicator	= 1;
			_crBlk[i][j].SetColour(BlockH264::CR);
			_crBlk[i][j].SetDcFlag(0);
			_crBlkTmp[i][j].SetColour(BlockH264::CR);
			_crBlkTmp[i][j].SetDcFlag(0);
			blkNum++;
		}//end for i & j...

  /// Vector Quantisation extensions.
  _vq_flag        = 0;
  _vq_distortion  = 0;     ///< Total VQ distortion (squared error) for the mb.
	for(i = 0; i < 4; i++)	
		for(j = 0; j < 4; j++)	
      _vq_LumCode[i][j] = 0;
	for(i = 0; i < 2; i++)	
		for(j = 0; j < 2; j++)
    {
      _vq_CbCode[i][j] = 0;
      _vq_CrCode[i][j] = 0;
    }//end for i & j...

}//end constructor.

MacroBlockH264::~MacroBlockH264(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/

/** Initialise macroblocks
Set all members to their default values and determine all neighbourhood
references, including those of the blocks. Assume 4:2:0 format. Each 
macroblock is initialised in raster scan order so that the member values 
will be valid for setting the neighbourhood references.
@param numMbRows		: Total num of macroblk rows in the image.
@param numMbCols		: Total num	of macroblk cols in the image.
@param startMbIndex	: Start index in raster scan order of the macroblks to be initialised.
@param endMbIndex		: End index in raster scan order of the macroblks to be initialised.
@param slice				: Slice to allocate macroblocks to.
@param mb						: 2-D array of macroblocks to initialise.
@return							: Success = 1, fail = 0.
*/
int MacroBlockH264::Initialise(int numMbRows, int numMbCols, int startMbIndex, int endMbIndex, int slice, MacroBlockH264** mb)
{
	int i,j,x,y,z,col,row;

	/// Macroblocks are to be processed.
	int startMbCol	= startMbIndex % numMbCols;
	int startMbRow	= startMbIndex / numMbCols;
	int endMbCol		= endMbIndex % numMbCols;
	int endMbRow		= endMbIndex / numMbCols;
	if((startMbRow >= numMbRows)||(endMbRow >= numMbRows))
		return(0);

	/// Parse the slice in raster order only.
	int index = startMbIndex;
	for(row = startMbRow; row <= endMbRow; row++)
		for(col = startMbCol; col <= endMbCol; col++, index++)
		{
			mb[row][col]._mbIndex = index;
			mb[row][col]._slice		= slice;

			/// The top-left corner of this macroblock in pel units assuming 4:2:0 chr dimensions.
			mb[row][col]._offLumY = row * 16;
			mb[row][col]._offLumX = col * 16;
			mb[row][col]._offChrY = row * 8;
			mb[row][col]._offChrX = col * 8;

			/// Find neighbouring macroblocks within the boundaries of the image and within the
			/// same slice group. Mark unavailable macroblocks by a NULL reference.
			x = col - 1;	///< Go left.
			y = row - 1;	///< Go above.
			z = col + 1;	///< Go right.
			mb[row][col]._leftMb = NULL;	///< Left.
			if(x >= 0)	
			{
				if(mb[row][x]._slice == slice)	///< Of the same slice.
					mb[row][col]._leftMb = &(mb[row][x]);
			}//end if x...
			mb[row][col]._aboveLeftMb	= NULL;	///< Above left.
			if((x >= 0)&&(y >= 0))	
			{
				if(mb[y][x]._slice == slice)
					mb[row][col]._aboveLeftMb = &(mb[y][x]);
			}//end if x & y...
			mb[row][col]._aboveMb = NULL;	///< Above.
			if(y >= 0)	
			{
				if(mb[y][col]._slice == slice)
					mb[row][col]._aboveMb = &(mb[y][col]);
			}//end if y...
			mb[row][col]._aboveRightMb	= NULL;	///< Above right.
			if((z >= 0)&&(z < numMbCols)&&(y >= 0))	
			{
				if(mb[y][z]._slice == slice)
					mb[row][col]._aboveRightMb = &(mb[y][z]);
			}//end if z & y...

			/// Set the block offsets within the macroblock with top-left corner
			/// of macroblock as (0,0) coordinate. Set the neighbourhood for
			/// each 4x4 block that is required for the context-aware entropy
			/// encoding.
			MacroBlockH264* pMb = &(mb[row][col]);
			for(i = 0; i < 4; i++)
				for(j = 0; j < 4; j++)
				{
					/// Lum.
					pMb->_lumBlk[i][j]._offX	= j*4;
					pMb->_lumBlk[i][j]._offY	= i*4;

					if(i == 0)	///< Falls into macroblock above and in row 3.
					{
						if(pMb->_aboveMb != NULL)	///< Test that there is an available macroblock above.
							pMb->_lumBlk[i][j]._blkAbove = &((pMb->_aboveMb)->_lumBlk[3][j]);	///< Col aligned.
						else
							pMb->_lumBlk[i][j]._blkAbove = NULL;	///< The block above is not availabe.
					}//end if i...
					else
						pMb->_lumBlk[i][j]._blkAbove = &(pMb->_lumBlk[i-1][j]); ///< In this macroblock.

					if(j == 0)	///< Falls into macroblock to the left and in col 3.
					{
						if(pMb->_leftMb != NULL)	///< Test if the macroblock to the left is available.
							pMb->_lumBlk[i][j]._blkLeft = &((pMb->_leftMb)->_lumBlk[i][3]);	///< Row aligned.
						else
							pMb->_lumBlk[i][j]._blkLeft = NULL;	///< The block to the left is not available.
					}//end if j...
					else
						pMb->_lumBlk[i][j]._blkLeft = &(pMb->_lumBlk[i][j-1]); ///< In this macroblock.
					/// Chr.
					if((i < 2)&&(j < 2))
					{
						pMb->_cbBlk[i][j]._offX	= j*4;
						pMb->_cbBlk[i][j]._offY	= i*4;
						pMb->_crBlk[i][j]._offX	= j*4;
						pMb->_crBlk[i][j]._offY	= i*4;
						if(i == 0)	///< Falls into macroblock above and in row 1.
						{
							if(pMb->_aboveMb != NULL)	///< Test that there is an available macroblock above.
							{
								pMb->_cbBlk[i][j]._blkAbove = &((pMb->_aboveMb)->_cbBlk[1][j]);	///< Col aligned.
								pMb->_crBlk[i][j]._blkAbove = &((pMb->_aboveMb)->_crBlk[1][j]);
							}//end if _aboveMb...
							else	///< The blocks above are not availabe.
							{
								pMb->_cbBlk[i][j]._blkAbove = NULL;	
								pMb->_crBlk[i][j]._blkAbove = NULL;
							}//end else...
						}//end if i...
						else	///< In this macroblock.
						{
							pMb->_cbBlk[i][j]._blkAbove = &(pMb->_cbBlk[i-1][j]); 
							pMb->_crBlk[i][j]._blkAbove = &(pMb->_crBlk[i-1][j]);
						}//end else...

						if(j == 0)	///< Falls into macroblock to the left and in col 1.
						{
							if(pMb->_leftMb != NULL)	///< Test that there is an available macroblock to the left.
							{
								pMb->_cbBlk[i][j]._blkLeft = &((pMb->_leftMb)->_cbBlk[i][1]);	///< Row aligned.
								pMb->_crBlk[i][j]._blkLeft = &((pMb->_leftMb)->_crBlk[i][1]);
							}//end if _leftMb...
							else	///< The blocks above are not availabe.
							{
								pMb->_cbBlk[i][j]._blkLeft = NULL;	
								pMb->_crBlk[i][j]._blkLeft = NULL;
							}//end else...
						}//end if j...
						else	///< In this macroblock.
						{
							pMb->_cbBlk[i][j]._blkLeft = &(pMb->_cbBlk[i][j-1]);
							pMb->_crBlk[i][j]._blkLeft = &(pMb->_crBlk[i][j-1]);
						}//end else...
					}//end if i & j...
				}//end for i & j...

				/// The DC blocks. There is only one DC block per macroblock therefore all
				/// pel offsets are (0,0). Strangely, for coeff counting in the context-aware
				/// process referencing the above and left blocks is required, not other macroblock 
				/// DC blocks, I think.
				pMb->_lumDcBlk._offX	= 0;
				pMb->_lumDcBlk._offY	= 0;
				pMb->_cbDcBlk._offX		= 0;
				pMb->_cbDcBlk._offY		= 0;
				pMb->_crDcBlk._offX		= 0;
				pMb->_crDcBlk._offY		= 0;
				
				if(pMb->_aboveMb != NULL)	///< Test that there is an available macroblock above.
				{
					pMb->_lumDcBlk._blkAbove	= &((pMb->_aboveMb)->_lumBlk[3][0]);	///< Bottom left block of macroblock above.
					pMb->_cbDcBlk._blkAbove		= &((pMb->_aboveMb)->_cbBlk[1][0]);
					pMb->_crDcBlk._blkAbove		= &((pMb->_aboveMb)->_crBlk[1][0]);
				}//end if _aboveMb...
				else
				{
					pMb->_lumDcBlk._blkAbove	= NULL; ///< Macroblock above not available.
					pMb->_cbDcBlk._blkAbove		= NULL;
					pMb->_cbDcBlk._blkAbove		= NULL;
				}//end else...
				if(pMb->_leftMb != NULL)	///< Test that there is an available macroblock to the left.
				{
					pMb->_lumDcBlk._blkLeft	= &((pMb->_leftMb)->_lumBlk[0][3]);	///< Top right block of macroblock to the left.
					pMb->_cbDcBlk._blkLeft	= &((pMb->_leftMb)->_cbBlk[0][1]);
					pMb->_crDcBlk._blkLeft	= &((pMb->_leftMb)->_crBlk[0][1]);
				}//end if _leftMb...
				else
				{
					pMb->_lumDcBlk._blkLeft		= NULL; ///< Macroblock to the left not available.
					pMb->_cbDcBlk._blkLeft		= NULL;
					pMb->_cbDcBlk._blkLeft		= NULL;
				}//end else...

		}//end for row & col...

	return(1);
}//end Initialise.

/** Set the coded block pattern member.
After quantisation the Lum and Chr block patterns are calculated from
examining the zero/non-zero status of each 4x4 block in their 8x8 block
groups. The _codedBlkPatternLum, _codedBlkPatternChr and _coded_blk_pattern
members are set and each 4x4 block's coded status is synchronized to this
pattern.
@param mb	: Macroblock to set.
return		: None.
*/
void MacroBlockH264::SetCodedBlockPattern(MacroBlockH264* mb)
{
	int i;

	if(mb->_intraFlag)
		mb->_blkParam[MBH264_LUM_DC].pBlk->SetCoded(1);	/// Blk = -1 Lum DC always on.
	else
		mb->_blkParam[MBH264_LUM_DC].pBlk->SetCoded(0);

	/// Iterate through each 4x4 block and set the coded pattern according to the
	/// associated 8x8 block position. One bit represents a coded/not coded flag 
	/// for each 8x8 block. For Intra_16x16 blocks, if any one of the 4x4 Lum blocks 
	/// are non-zero then every block is marked as coded.
	mb->_codedBlkPatternLum = 0;
	if(mb->_intraFlag && (mb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
		{
			if(!mb->_blkParam[i].pBlk->IsZero())
				break;
		}//end for i...
		/// ...then go back and mark all 4x4 blocks as coded within an active 8x8 block.
		if(i <= MBH264_LUM_3_3)	///< At least one block is non-zero.
		{
			for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
				mb->_blkParam[i].pBlk->SetCoded(1);
			mb->_codedBlkPatternLum = 15;
		}//end if i...
		else
		{
			for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
				mb->_blkParam[i].pBlk->SetCoded(0);
		}//end else...
	}//end if _intraFlag...
	else
	{
		for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
		{
			if(!mb->_blkParam[i].pBlk->IsZero())
				mb->_codedBlkPatternLum |= (1 << ((i - 1)/4));
		}//end for i...
		/// ...then go back and mark all 4x4 blocks as coded within an active 8x8 block.
		for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
		{
			if( mb->_codedBlkPatternLum & (1 << ((i - 1)/4)) )
				mb->_blkParam[i].pBlk->SetCoded(1);
		}//end for i...
	}//end else...

	/// For Chr, if any AC block is non-zero then they are all set as coded.
	mb->_codedBlkPatternChr = 2;
	for(i = MBH264_CB_0_0; i <= MBH264_CR_1_1; i++)	///< 19...26
	{
		if(!mb->_blkParam[i].pBlk->IsZero())
			break;	///< Non-zero found.
	}//end for i...
	if(i > MBH264_CR_1_1)	///< AC blocks are all zeros.
	{
		if( mb->_cbDcBlk.IsZero() && mb->_crDcBlk.IsZero() )
			mb->_codedBlkPatternChr = 0;
		else
		{
			mb->_codedBlkPatternChr = 1;
			mb->_cbDcBlk.SetCoded(1);	///< Force both DC blocks to be marked as coded.
			mb->_crDcBlk.SetCoded(1);
		}//end else...
	}//end if i...
	else
	{
		/// At least one AC block is non-zero so set all DC and AC blocks as coded.
		for(i = MBH264_CB_DC; i <= MBH264_CR_1_1; i++)	///< 17...26
			mb->_blkParam[i].pBlk->SetCoded(1);
	}//end else...

	/// Assemble the bit pattern to be coded onto the bit stream.
	mb->_coded_blk_pattern = mb->_codedBlkPatternLum | (mb->_codedBlkPatternChr << 4);

}//end SetCodedBlockPattern.

/** Get the coded block pattern member.
Pull out and set the _codedBlkPatternLum and _codedBlkPatternChr members
from the _coded_blk_pattern member decoded from the stream. Then set each 
4x4 block's coded status synchronized to this pattern.
@param mb	: Macroblock to set.
return		: None.
*/
void MacroBlockH264::GetCodedBlockPattern(MacroBlockH264* mb)
{
	int i;

	/// Disassemble the bit pattern to determine which blocks are to be decoded.
	mb->_codedBlkPatternLum = mb->_coded_blk_pattern & 0x0000000F;
	mb->_codedBlkPatternChr = (mb->_coded_blk_pattern >> 4) & 0x00000003;

	mb->_blkParam[MBH264_LUM_DC].pBlk->SetCoded(1);	/// Blk = -1 Lum DC always on.

	/// Map 4x4 block patterns to 8x8 blocks.
	for(i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)	///< 1..16
	{
		if( mb->_codedBlkPatternLum & (1 << ((i - 1)/4)) )
			mb->_blkParam[i].pBlk->SetCoded(1);
		else
			mb->_blkParam[i].pBlk->SetCoded(0);
	}//end for i...

	if(mb->_codedBlkPatternChr != 2)	///< Chr AC blks are zero.
	{
		for(i = MBH264_CB_DC; i <= MBH264_CR_1_1; i++)	///< Default all to zero including DC blocks.
			mb->_blkParam[i].pBlk->SetCoded(0);
		if(mb->_codedBlkPatternChr == 1)
		{
			mb->_cbDcBlk.SetCoded(1);	///< Force both DC blocks to be marked as coded.
			mb->_crDcBlk.SetCoded(1);
		}//end if _codedBlkPatternChr...
	}//end if _codedBlkPatternChr...
	else	///< Set all chr blocks as coded.
	{
		for(i = MBH264_CB_DC; i <= MBH264_CR_1_1; i++)
			mb->_blkParam[i].pBlk->SetCoded(1);
	}//end else...

}//end GetCodedBlockPattern.

/** Set the macroblock type member.
Set the type according to the macroblock prediction mode and the Lum and 
Chr coded block patterns. Sets the _mb_type member.
@param mb					: Macroblock to set.
@param sliceType	: Slice type that this macroblock belongs to.
return						: None.
*/
void MacroBlockH264::SetType(MacroBlockH264* mb, int sliceType)
{
	/// Slice type values:
	/// P_Slice		    = 0;
	/// B_Slice		    = 1;
	/// I_Slice		    = 2;
	/// SP_Slice	    = 3;
	/// SI_Slice	    = 4;
	/// P_Slice_All		= 5;
	/// B_Slice_All		= 6;
	/// I_Slice_All		= 7;
	/// SP_Slice_All	= 8;
	/// SI_Slice_All	= 9;
	int type = 0;
	if(mb->_intraFlag)
	{
		if(mb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
		{
			type = 1;
			if(mb->_codedBlkPatternLum)	///< Always either 0 or 15 in 16x16 mode.
				type += 12;
			type += ((4 * mb->_codedBlkPatternChr) + mb->_intra16x16PredMode);
		}//end if Intra_16x16...
	}//end if _intraFlag...
	
	if((sliceType == 0)||(sliceType == 5))	///< P_Slice
	{
		if(!mb->_intraFlag)
			type = mb->_mbPartPredMode;
		else
			type += 5;
	}//end if sliceType...

	mb->_mb_type = type;
}//end SetType.

/** Get the prediction modes.
Pull out and set the _intraFlag, _mbPartPredMode and, if Intra_16x16 mode 
then also set the _coded_blk_pattern member	from the _mb_type member decoded 
from the stream. If not Intra_16x16 then GetCodedBlockPattern() should be called 
after this method.
@param mb					: Macroblock to set.
@param sliceType	: Slice type that this macroblock belongs to.
return						: None.
*/
void MacroBlockH264::UnpackMbType(MacroBlockH264* mb, int sliceType)
{
	/// Slice type values:
	/// P_Slice		    = 0;
	/// B_Slice		    = 1;
	/// I_Slice		    = 2;
	/// SP_Slice	    = 3;
	/// SI_Slice	    = 4;
	/// P_Slice_All		= 5;
	/// B_Slice_All		= 6;
	/// I_Slice_All		= 7;
	/// SP_Slice_All	= 8;
	/// SI_Slice_All	= 9;
	int type = mb->_mb_type;
	mb->_intraFlag = 0;
	if((sliceType == 2)||(sliceType == 7))	///< I_Slice
	{
		mb->_intraFlag = 1;
	}//end if I_Slice...
	else								                    ///< P_Slice
	{
		if(type > 4)
		{
			mb->_intraFlag = 1;
			type -= 5;
		}//end if type...
	}//end else...

	if(mb->_intraFlag)
	{
		if(type == 0)
			mb->_mbPartPredMode = Intra_4x4;
		else
		{
			mb->_mbPartPredMode = Intra_16x16;
			/// Coded block patterns and prediction modes are also embedded.
			mb->_intra16x16PredMode = Intra16x16ModeTable[type-1][0];
			mb->_coded_blk_pattern	= Intra16x16ModeTable[type-1][2] | (Intra16x16ModeTable[type-1][1] << 4);
		}//end else...
	}//end if _intraFlag...
	else
		mb->_mbPartPredMode = type;

}//end UnpackMbType.

/** Test condition where skipped macroblock will force the motion vector to zero.
The prediction for the macroblock motion vector is either the median of the 
neighbouring macroblock vectors or (0,0) under some conditions of the macroblock 
neighbourhood. Defined in ITU-T Recommendation H.264 (03/2005) Section 8.4.1.1 p138.
@param mb					: Macroblock to set.
@return						: Condition for forcing the zero vector.
*/
bool MacroBlockH264::SkippedZeroMotionPredCondition(MacroBlockH264* mb)
{
	bool ret = false;

  if( (mb->_leftMb == NULL)||(mb->_aboveMb == NULL) )
    ret = true;
  else  ///< Both left and above exist.
  {
		if( ( (mb->_leftMb->_mvX[MacroBlockH264::_16x16] == 0) && (mb->_leftMb->_mvY[MacroBlockH264::_16x16] == 0)) ||
        ( (mb->_aboveMb->_mvX[MacroBlockH264::_16x16] == 0) && (mb->_aboveMb->_mvY[MacroBlockH264::_16x16] == 0)) )
        ret = true;
  }//end else...

  return(ret);
}//end SkippedZeroMotionPredCondition.

/** Predict the macroblock motion vector.
The prediction for the macroblock motion vector is the median of the 
neighbouring macroblock vectors. Special conditions apply when the
neighbours are outside of the image space or in another slice. This 
method assumes that all the (_mvX[],_mvY) values are correct before 
being called.
@param mb					: Macroblock to test.
@param mvpx				: Reference to returned predicted horiz component.
@param mvpy				: Reference to returned predicted vert component.
return						: None.
*/
void MacroBlockH264::GetMbMotionMedianPred(MacroBlockH264* mb, int* mvpx, int* mvpy)
{
	// TODO: Only the 16x16 prediction case is considered here. All other cases still to be coded.

	int Ax = 0;
	int Ay = 0;
	int Bx = 0;
	int By = 0;
	int Cx = 0;
	int Cy = 0;

	/// All intra neighbours are set to have zero vectors.
	if(mb->_leftMb != NULL)	///< A
	{
		if( !(mb->_leftMb)->_intraFlag )
		{
			Ax = (mb->_leftMb)->_mvX[MacroBlockH264::_16x16];
			Ay = (mb->_leftMb)->_mvY[MacroBlockH264::_16x16];
		}//end if _intraFlag...
	}//end if _leftMb...
	if(mb->_aboveMb != NULL)	///< B
	{
		if( !(mb->_aboveMb)->_intraFlag )
		{
			Bx = (mb->_aboveMb)->_mvX[MacroBlockH264::_16x16];
			By = (mb->_aboveMb)->_mvY[MacroBlockH264::_16x16];
		}//end if _intraFlag...
	}//end if _aboveMb...
	if(mb->_aboveRightMb != NULL)	///< C
	{
		if( !(mb->_aboveRightMb)->_intraFlag )
		{
			Cx = (mb->_aboveRightMb)->_mvX[MacroBlockH264::_16x16];
			Cy = (mb->_aboveRightMb)->_mvY[MacroBlockH264::_16x16];
		}//end if _intraFlag...
	}//end if _aboveRightMb...
	else	///< Replace C with D (if D exists)
	{
		if(mb->_aboveLeftMb != NULL)	/// D
		{
			if( !(mb->_aboveLeftMb)->_intraFlag )
			{
				Cx = (mb->_aboveLeftMb)->_mvX[MacroBlockH264::_16x16];
				Cy = (mb->_aboveLeftMb)->_mvY[MacroBlockH264::_16x16];
			}//end if _intraFlag...
		}//end if D...
	}//end else !C...

	/// Handle the special case of !B and !C by replacing them with A.
	if( (mb->_aboveMb == NULL) && (mb->_aboveRightMb == NULL) )
	{
		Bx = Ax;
		By = Ay;
		Cx = Ax;
		Cy = Ay;
	}//end !B and !C...

	*mvpx = mb->Median(Ax, Bx, Cx);
	*mvpy = mb->Median(Ay, By, Cy);
}//end GetMbMotionMedianPred.

/** Calc the median of 3 numbers.
@param x	:	1st num.
@param y	:	2nd num.
@param z	:	3rd num.
@return		: The median of x, y and z.
*/
int MacroBlockH264::Median(int x, int y, int z)
{
	int min,max;

	// min = MIN(x,MIN(y,z)) and max = MAX(x,MAX(y,z)).
	if( (y - z) < 0 )	{	min = y;	max = z;	}
	else { min = z; max = y; }
	if(x < min) min = x;
	if(x > max) max = x;
	// Median.
	int result = x + y + z - min - max;

	return(result);
}//end Median.

/** Copy the contents of blocks to the temp blocks.
The block numbers in the parameter list refer to their array position.
@param mb				: Macroblock to process.
@param startBlk	: Position of first block to copy.
@param endBlk		: Position of last block to copy.
@return					: none.
*/
void MacroBlockH264::CopyBlksToTmpBlks(MacroBlockH264* mb, int startBlk, int endBlk)
{
	if( (endBlk < MBH264_NUM_BLKS) && (startBlk >= 0) ) ///< Array range check.
	{
		for(int i = startBlk; i <= endBlk; i++)
			mb->_blkParam[i].pBlkTmp->CopyBlock(mb->_blkParam[i].pBlk);
	}//end if endBlk...
}//end CopyBlksToTmpBlks.

/** Copy the coeff mem of blocks to the temp blocks.
The block numbers in the parameter list refer to their array position. No bounds range
checking is done.
@param mb				: Macroblock to process.
@param startBlk	: Position of first block to copy.
@param endBlk		: Position of last block to copy.
@return					: none.
*/
void MacroBlockH264::CopyBlksToTmpBlksCoeffOnly(MacroBlockH264* mb, int startBlk, int endBlk)
{
	for(int i = startBlk; i <= endBlk; i++)
    mb->_blkParam[i].pBlk->Copy((void *)(mb->_blkParam[i].pBlkTmp->GetBlk()));
}//end CopyBlksToTmpBlks.

/** Load macroblock from image.
Copy the YCbCr values from the image colour components specified in the parameter list
into the macroblock. It assumes that the image overlay is of appropriate size.
@param mb				:	Macroblock to load.
@param lum			: Lum img overlay.
@param lumoffx	: X fffset for the Lum overlay.
@param lumoffy	: Y offset for the Lum overlay.
@param cb				: Cb img overlay.
@param cr				: Cb img overlay.
@param chroffx	: X offset for the Chr overlay.
@param chroffy	: Y offset for the Chr overlay.
*/
void MacroBlockH264::LoadBlks(MacroBlockH264* mb, OverlayMem2Dv2* lum, int lumoffx, int lumoffy, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr, int chroffx, int chroffy)
{
	int blk;

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// each image colour component.

	lum->SetOverlayDim(4, 4);
	for(blk = MBH264_LUM_0_0; blk <= MBH264_LUM_3_3; blk++)
	{
		BlockH264* pBlk = mb->_blkParam[blk].pBlk;
		/// Align the block with the image space.
		lum->SetOrigin(lumoffx + pBlk->_offX, lumoffy + pBlk->_offY);
		/// Read from the image mem into the block.
		lum->Read(*(pBlk->GetBlkOverlay()));
	}//end for blk...

	cb->SetOverlayDim(4, 4);
	for(blk = MBH264_CB_0_0; blk <= MBH264_CB_1_1; blk++)
	{
		BlockH264* pBlk = mb->_blkParam[blk].pBlk;
		/// Align the block with the image space.
		cb->SetOrigin(chroffx + pBlk->_offX, chroffy + pBlk->_offY);
		/// Read from the image mem into the block.
		cb->Read(*(pBlk->GetBlkOverlay()));
	}//end for blk...

	cr->SetOverlayDim(4, 4);
	for(blk = MBH264_CR_0_0; blk <= MBH264_CR_1_1; blk++)
	{
		BlockH264* pBlk = mb->_blkParam[blk].pBlk;
		/// Align the block with the image space.
		cr->SetOrigin(chroffx + pBlk->_offX, chroffy + pBlk->_offY);
		/// Read from the image mem into the block.
		cr->Read(*(pBlk->GetBlkOverlay()));
	}//end for blk...

}//end LoadBlks.

/** Store macroblock to image.
Copy the YCbCr values from the macroblock into the image colour components specified in the 
parameter list. It assumes that the image overlay is of appropriate size.
@param mb					:	Macroblock to store.
@param lum				: Lum img overlay.
@param lumoffx		: X offset for the Lum overlay.
@param lumoffy		: Y offset for the Lum overlay.
@param cb					: Cb img overlay.
@param cr					: Cb img overlay.
@param chroffx		: X offset for the Chr overlay.
@param chroffy		: Y offset for the Chr overlay.
@param tmpBlkFlag	: Store from temp blocks.
*/
void MacroBlockH264::StoreBlks(MacroBlockH264* mb, OverlayMem2Dv2* lum, int lumoffx, int lumoffy, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr, int chroffx, int chroffy, int tmpBlkFlag)
{

	int					i;
	BlockH264*	pLumBlk;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	if(tmpBlkFlag)
	{
		pLumBlk = &(mb->_lumBlkTmp[0][0]);
		pCbBlk	= &(mb->_cbBlkTmp[0][0]);
		pCrBlk	= &(mb->_crBlkTmp[0][0]);
	}//end if tmpBlkFlag...
	else
	{
		pLumBlk = &(mb->_lumBlk[0][0]);
		pCbBlk	= &(mb->_cbBlk[0][0]);
		pCrBlk	= &(mb->_crBlk[0][0]);
	}//end else...

	/// Store all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks into 
	/// each image colour component.

	lum->SetOverlayDim(4, 4);
	for(i = 0; i < 16; i++)
	{
		/// Align the block with the image space.
		lum->SetOrigin(lumoffx + pLumBlk->_offX, lumoffy + pLumBlk->_offY);
		/// Read from the image mem into the block.
		lum->Write4x4(*(pLumBlk->GetBlkOverlay()));
		/// Next block.
		pLumBlk++;
	}//end for i...

	cb->SetOverlayDim(4, 4);
	for(i = 0; i < 4; i++)
	{
		cb->SetOrigin(chroffx + pCbBlk->_offX, chroffy + pCbBlk->_offY);
		cb->Write4x4(*(pCbBlk->GetBlkOverlay()));
		pCbBlk++;
	}//end for i...

	cr->SetOverlayDim(4, 4);
	for(i = 0; i < 4; i++)
	{
		cr->SetOrigin(chroffx + pCrBlk->_offX, chroffy + pCrBlk->_offY);
		cr->Write4x4(*(pCrBlk->GetBlkOverlay()));
		pCrBlk++;
	}//end for i...

}//end StoreBlks.

/** Copy from another macroblock.
Match the mem size and copy all members and macroblock
data.
@param pMbInto	: Macroblock to copy into.
@param pMbFrom	: Macroblock to copy from.
@return					: 1/0 = success/failure.
*/
int MacroBlockH264::CopyMarcoBlockProxy(MacroBlockH264* pMbInto, MacroBlockH264* pMbFrom)
{
	pMbInto->_offLumX				= pMbFrom->_offLumX;
	pMbInto->_offLumY				= pMbFrom->_offLumY;
	pMbInto->_offChrX				= pMbFrom->_offChrX;
	pMbInto->_offChrY				= pMbFrom->_offChrY;
	pMbInto->_mbIndex				= pMbFrom->_mbIndex;
	pMbInto->_slice					= pMbFrom->_slice;
	pMbInto->_leftMb				= pMbFrom->_leftMb;
	pMbInto->_aboveLeftMb		= pMbFrom->_aboveLeftMb;
	pMbInto->_aboveMb				= pMbFrom->_aboveMb;
	pMbInto->_aboveRightMb	= pMbFrom->_aboveRightMb;
	pMbInto->_mbQP					= pMbFrom->_mbQP;
	pMbInto->_mbEncQP				= pMbFrom->_mbEncQP;

	memcpy((void *)(&pMbInto->_mvX[0]), (const void *)(&pMbFrom->_mvX[0]), 16 * sizeof(int));
	memcpy((void *)(&pMbInto->_mvY[0]), (const void *)(&pMbFrom->_mvY[0]), 16 * sizeof(int));

	pMbInto->_intraFlag						= pMbFrom->_intraFlag;
	pMbInto->_mbPartPredMode			= pMbFrom->_mbPartPredMode;
	pMbInto->_mbSubPartPredMode		= pMbFrom->_mbSubPartPredMode;
	pMbInto->_intra16x16PredMode	= pMbFrom->_intra16x16PredMode;
	pMbInto->_intraChrPredMode		= pMbFrom->_intraChrPredMode;
	pMbInto->_codedBlkPatternChr	= pMbFrom->_codedBlkPatternChr;
	pMbInto->_codedBlkPatternLum	= pMbFrom->_codedBlkPatternLum;

	pMbInto->_mvDistortion	= pMbFrom->_mvDistortion;
	pMbInto->_mvRate				= pMbFrom->_mvRate;
	pMbInto->_include				= pMbFrom->_include;
	memcpy((void *)(&pMbInto->_distortion[0]), (const void *)(&pMbFrom->_distortion[0]), 52 * sizeof(int));
	memcpy((void *)(&pMbInto->_rate[0]), (const void *)(&pMbFrom->_rate[0]), 52 * sizeof(int));

	pMbInto->_skip							= pMbFrom->_skip;
	pMbInto->_mb_type						= pMbFrom->_mb_type;
	pMbInto->_sub_mb_type				= pMbFrom->_sub_mb_type;
	pMbInto->_coded_blk_pattern = pMbFrom->_coded_blk_pattern;
	pMbInto->_mb_qp_delta				= pMbFrom->_mb_qp_delta;

	memcpy((void *)(&pMbInto->_mvdX[0]), (const void *)(&pMbFrom->_mvdX[0]), 16 * sizeof(int));
	memcpy((void *)(&pMbInto->_mvdY[0]), (const void *)(&pMbFrom->_mvdY[0]), 16 * sizeof(int));

	for(int i = 0; i < MBH264_NUM_BLKS; i++)
	{
		pMbInto->_blkParam[i].pBlk->CopyBlock(pMbFrom->_blkParam[i].pBlk);
		pMbInto->_blkParam[i].pBlkTmp->CopyBlock(pMbFrom->_blkParam[i].pBlkTmp);
		pMbInto->_blkParam[i].rasterIndex					= pMbFrom->_blkParam[i].rasterIndex;
		pMbInto->_blkParam[i].neighbourIndicator	= pMbFrom->_blkParam[i].neighbourIndicator;
		pMbInto->_blkParam[i].dcSkipFlag					= pMbFrom->_blkParam[i].dcSkipFlag;
	}//end for i...

	return(1);
}//end CopyMarcoBlockProxy;

/** Check for equality with another macroblock.
Check all key members and main coeff blocks.
@param me	: Macroblock to compare.
@param mb	: Macroblock from which to compare.
@return		: 1/0 = equal/not equal.
*/
int MacroBlockH264::EqualsProxy(MacroBlockH264* me, MacroBlockH264* mb)
{
	if( (me->_mbQP != mb->_mbQP) ||
			(me->_mbEncQP != mb->_mbEncQP) ||
			(me->_mb_qp_delta != mb->_mb_qp_delta) ||
			(me->_mb_type != mb->_mb_type) ||
			(me->_sub_mb_type != mb->_sub_mb_type) ||
			(me->_skip != mb->_skip) ||
			(me->_intraFlag != mb->_intraFlag) ||
			(me->_coded_blk_pattern != mb->_coded_blk_pattern) ||
			(me->_codedBlkPatternLum != mb->_codedBlkPatternLum) ||
			(me->_codedBlkPatternChr != mb->_codedBlkPatternChr) ||
			(me->_mbPartPredMode != mb->_mbPartPredMode) ||
			(me->_mbSubPartPredMode != mb->_mbSubPartPredMode) )
		return(0);

	if(me->_intraFlag)
	{
		if(	(me->_intraChrPredMode != mb->_intraChrPredMode) ||
				(me->_intra16x16PredMode != mb->_intra16x16PredMode) )
			return(0);

		if(me->_mbPartPredMode == MacroBlockH264::Intra_16x16)
		{
		}//end if _mbPartPredMode...
	}//end if _intraFlag...
	else
	{
	}//end else...

	for(int i = 0; i < MBH264_NUM_BLKS; i++)
	{
		if( (!me->_blkParam[i].pBlk->Equals(mb->_blkParam[i].pBlk)) ||
				(me->_blkParam[i].rasterIndex					!= mb->_blkParam[i].rasterIndex) ||
				(me->_blkParam[i].neighbourIndicator	!= mb->_blkParam[i].neighbourIndicator) ||
				(me->_blkParam[i].dcSkipFlag					!= mb->_blkParam[i].dcSkipFlag) )
				return(0);
	}//end for i...

	return(1);
}//end EqualsProxy.

/** Check for coded coeff.
After SetCodedBlockPattern() method has been called the _coded_blk_pattern
member reflects the 8x8 block group coded coeff status. However, for Intra
macroblocks in Intra_16x16 modes, the Lum Dc block is not included and must
be done seperately. NB: THIS METHOD MUST ONLY BE CALLED AFTER SetCodedBlockPattern()
HAS BEEN CALLED ON THE MACROBLOCK. I.e. _coded_blk_pattern is valid.
@param mb	: Macroblock to test.
return		: 0/1 = All zero coeffs/At least one non-zero coeff.
*/
int MacroBlockH264::HasNonZeroCoeffsProxy(MacroBlockH264* mb)
{
	if(mb->_intraFlag && (mb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		if(!mb->_lumDcBlk.IsZero2())
			return(1);
	}//end if _intraFlag...

	if(mb->_coded_blk_pattern)	///< SetCodedBlockPattern() must have been called for _coded_blk_pattern to be valid.
		return(1);

	return(0);
}//end HasNonZeroCoeffsProxy.

/** Calculate the distortion between two overlays at this mb's postion.
Align the two lum and chr images over this mb and calculate the sum of square or abs error for
the three colour spaces. The image spaces must have identical width and height and match the mb 
initialisation settings. The format must be YCbCr 4:2:0 16x16:8x8:8x8.
@param  p1Y   : 1st Image lum overlay
@param  p1Cb  : 1st Image chr overlay
@param  p1Cr  :
@param  p2Y   : 2nd Image lum overlay
@param  p2Cb  : 2nd Image chr overlay
@param  p2Cr  :
@return       : Square/Absolute error distortion
*/
int MacroBlockH264::Distortion(OverlayMem2Dv2* p1Y, OverlayMem2Dv2* p1Cb, OverlayMem2Dv2* p1Cr, OverlayMem2Dv2* p2Y, OverlayMem2Dv2* p2Cb, OverlayMem2Dv2* p2Cr)
{
  int distortion = 0;
  int tmp1Width, tmp1Height, tmp1OrgX, tmp1OrgY;
  int tmp2Width, tmp2Height, tmp2OrgX, tmp2OrgY;

  /// Lum
  tmp1Width   = p1Y->GetWidth();
  tmp1Height  = p1Y->GetHeight();
  tmp1OrgX    = p1Y->GetOriginX();
  tmp1OrgY    = p1Y->GetOriginY();
  p1Y->SetOverlayDim(16,16);
  p1Y->SetOrigin(_offLumX, _offLumY);
  tmp2Width   = p2Y->GetWidth();
  tmp2Height  = p2Y->GetHeight();
  tmp2OrgX    = p2Y->GetOriginX();
  tmp2OrgY    = p2Y->GetOriginY();
  p2Y->SetOverlayDim(16,16);
  p2Y->SetOrigin(_offLumX, _offLumY);

#ifdef USE_ABSOLUTE_DIFFERENCE
  distortion = p1Y->Tad16x16( *p2Y );
#else
  distortion = p1Y->Tsd16x16( *p2Y );
#endif

  p1Y->SetOverlayDim(tmp1Width,tmp1Height);
  p1Y->SetOrigin(tmp1OrgX, tmp1OrgY);
  p2Y->SetOverlayDim(tmp2Width,tmp2Height);
  p2Y->SetOrigin(tmp2OrgX, tmp2OrgY);

  /// Cb
  tmp1Width   = p1Cb->GetWidth();
  tmp1Height  = p1Cb->GetHeight();
  tmp1OrgX    = p1Cb->GetOriginX();
  tmp1OrgY    = p1Cb->GetOriginY();
  p1Cb->SetOverlayDim(8,8);
  p1Cb->SetOrigin(_offChrX, _offChrY);
  tmp2Width   = p2Cb->GetWidth();
  tmp2Height  = p2Cb->GetHeight();
  tmp2OrgX    = p2Cb->GetOriginX();
  tmp2OrgY    = p2Cb->GetOriginY();
  p2Cb->SetOverlayDim(8,8);
  p2Cb->SetOrigin(_offChrX, _offChrY);

#ifdef USE_ABSOLUTE_DIFFERENCE
  distortion += p1Cb->Tad8x8( *p2Cb );
#else
  distortion += p1Cb->Tsd8x8( *p2Cb );
#endif
  p1Cb->SetOverlayDim(tmp1Width,tmp1Height);
  p1Cb->SetOrigin(tmp1OrgX, tmp1OrgY);
  p2Cb->SetOverlayDim(tmp2Width,tmp2Height);
  p2Cb->SetOrigin(tmp2OrgX, tmp2OrgY);

  /// Cr
  tmp1Width   = p1Cr->GetWidth();
  tmp1Height  = p1Cr->GetHeight();
  tmp1OrgX    = p1Cr->GetOriginX();
  tmp1OrgY    = p1Cr->GetOriginY();
  p1Cr->SetOverlayDim(8,8);
  p1Cr->SetOrigin(_offChrX, _offChrY);
  tmp2Width   = p2Cr->GetWidth();
  tmp2Height  = p2Cr->GetHeight();
  tmp2OrgX    = p2Cr->GetOriginX();
  tmp2OrgY    = p2Cr->GetOriginY();
  p2Cr->SetOverlayDim(8,8);
  p2Cr->SetOrigin(_offChrX, _offChrY);

#ifdef USE_ABSOLUTE_DIFFERENCE
  distortion += p1Cr->Tad8x8( *p2Cr );
#else
  distortion += p1Cr->Tsd8x8( *p2Cr );
#endif
  p1Cr->SetOverlayDim(tmp1Width,tmp1Height);
  p1Cr->SetOrigin(tmp1OrgX, tmp1OrgY);
  p2Cr->SetOverlayDim(tmp2Width,tmp2Height);
  p2Cr->SetOrigin(tmp2OrgX, tmp2OrgY);

  return(distortion);
}//end Distortion.

/** Calculate the distortion between two overlays at this mb's postion.
Same as above but for lum only. The image spaces must have identical width and height and match the mb 
initialisation settings. The format must be YCbCr 4:2:0 16x16:8x8:8x8.
@param  p1Y   : 1st Image lum overlay
@param  p2Y   : 2nd Image lum overlay
@return       : Square/Absolute error distortion
*/
int MacroBlockH264::Distortion(OverlayMem2Dv2* p1Y, OverlayMem2Dv2* p2Y)
{
  int distortion = 0;
  int tmp1Width, tmp1Height, tmp1OrgX, tmp1OrgY;
  int tmp2Width, tmp2Height, tmp2OrgX, tmp2OrgY;

  /// Lum
  tmp1Width   = p1Y->GetWidth();
  tmp1Height  = p1Y->GetHeight();
  tmp1OrgX    = p1Y->GetOriginX();
  tmp1OrgY    = p1Y->GetOriginY();
  p1Y->SetOverlayDim(16,16);
  p1Y->SetOrigin(_offLumX, _offLumY);
  tmp2Width   = p2Y->GetWidth();
  tmp2Height  = p2Y->GetHeight();
  tmp2OrgX    = p2Y->GetOriginX();
  tmp2OrgY    = p2Y->GetOriginY();
  p2Y->SetOverlayDim(16,16);
  p2Y->SetOrigin(_offLumX, _offLumY);

#ifdef USE_ABSOLUTE_DIFFERENCE
  distortion = p1Y->Tad16x16( *p2Y );
#else
  distortion = p1Y->Tsd16x16( *p2Y );
#endif

  p1Y->SetOverlayDim(tmp1Width,tmp1Height);
  p1Y->SetOrigin(tmp1OrgX, tmp1OrgY);
  p2Y->SetOverlayDim(tmp2Width,tmp2Height);
  p2Y->SetOrigin(tmp2OrgX, tmp2OrgY);

  return(distortion);
}//end Distortion.

/** Mark this macroblock onto the image.
For debugging.
@param  mb  : Macroblock to mark
@param  lum : Lum image space.
@param  cb  : Cb image space.
@param  cr  : Cr image space.
@return     : none.
*/
void MacroBlockH264::Mark(MacroBlockH264* mb, OverlayMem2Dv2* lum, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr)
{
  int i;

 	lum->SetOverlayDim(16, 16);
  lum->SetOrigin(mb->_offLumX, mb->_offLumY);
  for(i = 0; i < 16; i++)
  {
    lum->Write(i,0,0);      ///< Top row.
    lum->Write(i,15,0);     ///< Bottom row.
    lum->Write(0,i,0);      ///< Left col.
    lum->Write(15,i,0);     ///< Right col.
  }//end for i...

 	cb->SetOverlayDim(8, 8);
  cb->SetOrigin(mb->_offChrX, mb->_offChrY);
 	cr->SetOverlayDim(8, 8);
  cr->SetOrigin(mb->_offChrX, mb->_offChrY);
  for(i = 0; i < 8; i++)
  {
    cb->Write(i,0,127);     ///< Top row.
    cr->Write(i,0,127);     ///< Top row.
    cb->Write(i,7,127);     ///< Bottom row.
    cr->Write(i,7,127);     ///< Bottom row.
    cb->Write(0,i,127);     ///< Left col.
    cr->Write(0,i,127);     ///< Left col.
    cb->Write(7,i,127);     ///< Right col.
    cr->Write(7,i,127);     ///< Right col.
  }//end for i...

}//end Mark.

/** Dump the state variables of the macroblock to file.
For debugging.
@param  mb  : Macroblock to dump
@param  filename  : File to write into
@param  title     : Title of stored table data
@return     : none.
*/
void MacroBlockH264::Dump(MacroBlockH264* mb, char* filename, const char* title)
{
  int j; 

  MeasurementTable* pT = new MeasurementTable();
	pT->Create(18, 1);
	pT->SetTitle(title);
  
  pT->SetHeading(0, "Index");
  pT->SetHeading(1, "Type");
  pT->SetHeading(2, "SubType");
  pT->SetHeading(3, "Skip");
  pT->SetHeading(4, "QP");
  pT->SetHeading(5, "DeltaQP");
  pT->SetHeading(6, "IntraFlg");
  pT->SetHeading(7, "PartPredMode");
  pT->SetHeading(8, "SubPartPredMode");
  pT->SetHeading(9, "Intra16x16PartPredMode");
  pT->SetHeading(10, "IntraChrPredMode");
  pT->SetHeading(11, "mvX[0]");
  pT->SetHeading(12, "mvY[0]");
  pT->SetHeading(13, "mvdX[0]");
  pT->SetHeading(14, "mvdY[0]");
  pT->SetHeading(15, "CodeBlkPattern");
  pT->SetHeading(16, "CodeBlkPatternLum");
  pT->SetHeading(17, "CodeBlkPatternChr");

  for(j = 0; j < 18; j++)
    pT->SetDataType(j, MeasurementTable::INT);

	pT->WriteItem(0, 0, mb->_mbIndex);
	pT->WriteItem(1, 0, mb->_mb_type);
	pT->WriteItem(2, 0, mb->_sub_mb_type);
	pT->WriteItem(3, 0, mb->_skip);
	pT->WriteItem(4, 0, mb->_mbQP);
	pT->WriteItem(5, 0, mb->_mb_qp_delta);
	pT->WriteItem(6, 0, mb->_intraFlag);
	pT->WriteItem(7, 0, mb->_mbPartPredMode);
	pT->WriteItem(8, 0, mb->_mbSubPartPredMode);
	pT->WriteItem(9, 0, mb->_intra16x16PredMode);
	pT->WriteItem(10, 0, mb->_intraChrPredMode);
	pT->WriteItem(11, 0, mb->_mvX[0]);
	pT->WriteItem(12, 0, mb->_mvY[0]);
	pT->WriteItem(13, 0, mb->_mvdX[0]);
	pT->WriteItem(14, 0, mb->_mvdY[0]);
	pT->WriteItem(15, 0, mb->_coded_blk_pattern);
	pT->WriteItem(16, 0, mb->_codedBlkPatternLum);
	pT->WriteItem(17, 0, mb->_codedBlkPatternChr);

  pT->Save(filename, ",", 1);

  delete pT;
}//end Dump.


========== END FILE: CodecUtils/MacroBlockH264.cpp ==========

========== BEGIN FILE: CodecUtils/MacroBlockH264.h ==========
Bundle entry: 78
Original bytes: 19363
Original SHA-256: a9ea2ac9c35597d3527dfb3c95d3867ebef287998a4632ab35cdc123e0e037d8
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MacroBlockH264

TAG						: MBH264

FILE NAME			: MacroBlockH264.h

DESCRIPTION		: A class to hold H.264 macroblock specific data. Only static 
								methods that apply to macroblocks are used because it is 
								expected that there will be one MacroBlockH264() instantiation
								per overlay position on the picture.

COPYRIGHT			:	(c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MACROBLOCKH264_H
#define _MACROBLOCKH264_H

#pragma once

#include "BlockH264.h"

/*
---------------------------------------------------------------------------
	Constants.
---------------------------------------------------------------------------
*/
#define MBH264_LUM_DC				0
#define MBH264_LUM_0_0			1
#define MBH264_LUM_0_1			2
#define MBH264_LUM_1_0			3
#define MBH264_LUM_1_1			4
#define MBH264_LUM_0_2			5
#define MBH264_LUM_0_3			6
#define MBH264_LUM_1_2			7
#define MBH264_LUM_1_3			8
#define MBH264_LUM_2_0			9
#define MBH264_LUM_2_1			10
#define MBH264_LUM_3_0			11
#define MBH264_LUM_3_1			12
#define MBH264_LUM_2_2			13
#define MBH264_LUM_2_3			14
#define MBH264_LUM_3_2			15
#define MBH264_LUM_3_3			16
#define MBH264_CB_DC				17
#define MBH264_CR_DC				18
#define MBH264_CB_0_0				19
#define MBH264_CB_0_1				20
#define MBH264_CB_1_0				21
#define MBH264_CB_1_1				22
#define MBH264_CR_0_0				23
#define MBH264_CR_0_1				24
#define MBH264_CR_1_0				25
#define MBH264_CR_1_1				26

#define MBH264_NUM_BLKS			27

/// A list of these structs give the correct coding order and parameters to 
/// iterate through the blocks during encoding or decoding.
typedef struct _MBH264_CODING_STRUCT
{
	/// Block reference.
	BlockH264*	pBlk;
	BlockH264*	pBlkTmp;			///< A temporary working block.
	int					rasterIndex;	///< Mapping of this blk to its blk index in raster scan order.
	/// (< 0) = used directly, (0) = no neighbourhood check, (1) = do a neighbourhood check.
	int					neighbourIndicator;
	/// DC skip flag to use.
	int					dcSkipFlag;
} MBH264_CODING_STRUCT;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MacroBlockH264
{
public:
	MacroBlockH264(void);
	virtual ~MacroBlockH264(void);

/// Interface implementation.
public:
	/** Initialise macroblocks
	Set all members to their default values and determine all neighbourhood
	references, including those of the blocks. Assume 4:2:0 format. Each 
	macroblock is initialised in raster scan order so that the member values 
	will be valid for setting the neighbourhood references.
	@param numMbRows		: Total num of macroblk rows in the image.
	@param numMbCols		: Total num	of macroblk cols in the image.
	@param startMbIndex	: Start index in raster scan order of the macroblks to be initialised.
	@param endMbIndex		: End index in raster scan order of the macroblks to be initialised.
	@param slice				: Slice to allocate macroblocks to.
	@param mb						: 2-D array of macroblocks to initialise.
	@return							: Success = 1, fail = 0.
	*/
	static int Initialise(int numMbRows, int numMbCols, int startMbIndex, int endMbIndex, int slice, MacroBlockH264** mb);

	/** Map the lum quant parameter to the Chr quant parameter.
	This mapping is defined in ITU-T Rec. H.264 (03/2005) page 167
	Table 8-15. The chr coeffs are less harshly quantised than the
	lum coeffs.
	@param QPl	: Lum quant param.
	return			: Mapped chr quant param.
	*/
	static int GetQPc(int QPl) { return(QPltoQPcMap[QPl]); }

	/** Set the coded block pattern member.
	After quantisation the Lum and Chr block patterns are calculated from
	examining the zero/non-zero status of each 4x4 block in their 8x8 block
	groups. The _codedBlkPatternLum, _codedBlkPatternChr and _coded_blk_pattern
	members are set and each 4x4 block's coded status is synchronized to this
	pattern.
	@param mb	: Macroblock to set.
	return		: None.
	*/
	static void SetCodedBlockPattern(MacroBlockH264* mb);

	/** Get the coded block pattern member.
	Pull out and set the _codedBlkPatternLum and _codedBlkPatternChr members
	from the _coded_blk_pattern member decoded from the stream. Then set each 
	4x4 block's coded status synchronized to this pattern.
	@param mb	: Macroblock to set.
	return		: None.
	*/
	static void GetCodedBlockPattern(MacroBlockH264* mb);

	/** Set the macroblock type member.
	Set the type according to the macroblock prediction mode and the Lum and 
	Chr coded block patterns. Sets the _mb_type member.
	@param mb					: Macroblock to set.
	@param sliceType	: Slice type that this macroblock belongs to.
	return						: None.
	*/
	static void SetType(MacroBlockH264* mb, int sliceType);

	/** Unpack macroblock type to the prediction modes.
	Pull out and set the _intraFlag, _mbPartPredMode and, if Intra_16x16 mode 
	then also	set the _coded_blk_pattern member	from the _mb_type member decoded 
	from the stream. If not Intra_16x16 then GetCodedBlockPattern() should be called 
	after this method.
	@param mb					: Macroblock to set.
	@param sliceType	: Slice type that this macroblock belongs to.
	return						: None.
	*/
	static void UnpackMbType(MacroBlockH264* mb, int sliceType);

  /** Test condition where skipped macroblock forces the motion vector to zero.
  The prediction for the macroblock motion vector is either the median of the 
  neighbouring macroblock vectors or (0,0) under some conditions of the macroblock 
  neighbourhood. 
  @param mb					: Macroblock to set.
  return						: Condition for forcing the zero vector.
  */
  static bool SkippedZeroMotionPredCondition(MacroBlockH264* mb);

	/** Predict the macroblock motion vector.
	The prediction for the macroblock motion vector is the median of the 
	neighbouring macroblock vectors. Special conditions apply when the
	neighbours are outside of the image space or in another slice.
	@param mb					: Macroblock to set.
	@param mvpx				: Reference to returned predicted horiz component.
	@param mvpy				: Reference to returned predicted vert component.
	return						: None.
	*/
	static void GetMbMotionMedianPred(MacroBlockH264* mb, int* mvpx, int* mvpy);

	/** Calc the median of 3 numbers.
	@param x	:	1st num.
	@param y	:	2nd num.
	@param z	:	3rd num.
	@return		: The median of x, y and z.
	*/
	static int Median(int x, int y, int z);

	/** Copy the contents of blocks to the temp blocks.
	The block numbers in the parameter list refer to their array position.
	@param mb				: Macroblock to process.
	@param startBlk	: Position of first block to copy.
	@param endBlk		: Position of last block to copy.
	@return					: none.
	*/
	static void CopyBlksToTmpBlks(MacroBlockH264* mb, int startBlk, int endBlk);
	static void CopyBlksToTmpBlksCoeffOnly(MacroBlockH264* mb, int startBlk, int endBlk);

	/** Load macroblock from image.
	Copy the YCbCr values from the image colour components specified in the parameter list
	into the macroblock. It assumes that the image overlay origin is preset to the upper left
	corner for both Lum and Chr.
	@param mb				:	Macroblock to load.
	@param lum			: Lum img overlay.
	@param lumoffx	: X fffset for the Lum overlay.
	@param lumoffy	: Y offset for the Lum overlay.
	@param cb				: Cb img overlay.
	@param cr				: Cb img overlay.
	@param chroffx	: X offset for the Chr overlay.
	@param chroffy	: Y offset for the Chr overlay.
	*/
	static void LoadBlks(MacroBlockH264* mb, OverlayMem2Dv2* lum, int lumoffx, int lumoffy, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr, int chroffx, int chroffy);

	/** Store macroblock to image.
	Copy the YCbCr values from the macroblock into the image colour components specified in the 
	parameter list. It assumes that the image overlay is of appropriate size.
	@param mb				:	Macroblock to store.
	@param lum			: Lum img overlay.
	@param lumoffx	: X fffset for the Lum overlay.
	@param lumoffy	: Y offset for the Lum overlay.
	@param cb				: Cb img overlay.
	@param cr				: Cb img overlay.
	@param chroffx	: X offset for the Chr overlay.
	@param chroffy	: Y offset for the Chr overlay.
	@param tmpBlkFlag	: Store from temp blocks.
	*/
	static void StoreBlks(MacroBlockH264* mb, OverlayMem2Dv2* lum, int lumoffx, int lumoffy, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr, int chroffx, int chroffy, int tmpBlkFlag);

	/** Check for equality with another macroblock.
	Check all key members and main coeff blocks.
	@param me	: Macroblock to compare.
	@param mb	: Macroblock from which to compare.
	@return		: 1/0 = equal/not equal.
	*/
	int Equals(MacroBlockH264* mb) { return(EqualsProxy(this, mb)); }
	static int EqualsProxy(MacroBlockH264* me, MacroBlockH264* mb);

	/** Copy from another macroblock.
	Match the mem size and copy all members and macroblock
	data.
	@param pMb	: Macroblock to copy from.
	@return			: 1/0 = success/failure.
	*/
	int CopyMacroBlock(MacroBlockH264* pMb) { return(CopyMarcoBlockProxy(this, pMb)); }
	static int CopyMarcoBlockProxy(MacroBlockH264* pMbInto, MacroBlockH264* pMbFrom);

	/** Check for coded coeff.
	After SetCodedBlockPattern() method has been called the _coded_blk_pattern
	member reflects the 8x8 block group coded coeff status. However, for Intra
	macroblocks in Intra_16x16 modes, the Lum Dc block is not included and must
	be done seperately. NB: THIS METHOD MUST ONLY BE CALLED AFTER SetCodedBlockPattern()
	HAS BEEN CALLED ON THE MACROBLOCK. I.e. _coded_blk_pattern is valid.
	@param mb	: Macroblock to test.
	return		: 0/1 = All zero coeffs/At least one non-zero coeff.
	*/
	int HasNonZeroCoeffs(void) { return(HasNonZeroCoeffsProxy(this)); }
	static int HasNonZeroCoeffsProxy(MacroBlockH264* mb);

  /** Calculate the distortion between two overlays at this mb's postion.
  Align the two lum and chr images over this mb and calculate the sum of square or abs error for
  the three colour spaces. The image spaces must have identical width and height and match the mb 
  initialisation settings. The format must be YCbCr 4:2:0 16x16:8x8:8x8.
  @param  p1Y   : 1st Image lum overlay
  @param  p1Cb  : 1st Image chr overlay
  @param  p1Cr  :
  @param  p2Y   : 2nd Image lum overlay
  @param  p2Cb  : 2nd Image chr overlay
  @param  p2Cr  :
  @return       : Square/Absolute error distortion
  */
  int Distortion(OverlayMem2Dv2* p1Y, OverlayMem2Dv2* p1Cb, OverlayMem2Dv2* p1Cr, OverlayMem2Dv2* p2Y, OverlayMem2Dv2* p2Cb, OverlayMem2Dv2* p2Cr);

  /** Calculate the distortion between two overlays at this mb's postion.
  Same as above but for lum only. The image spaces must have identical width and height and match the mb 
  initialisation settings. The format must be YCbCr 4:2:0 16x16:8x8:8x8.
  @param  p1Y   : 1st Image lum overlay
  @param  p2Y   : 2nd Image lum overlay
  @return       : Square/Absolute error distortion
  */
  int Distortion(OverlayMem2Dv2* p1Y, OverlayMem2Dv2* p2Y);

  /** Mark this macroblock onto the image.
  For debugging.
  @param  mb  : Macroblock to mark
  @param  lum : Lum image space.
  @param  cb  : Cb image space.
  @param  cr  : Cr image space.
  @return     : none.
  */
  static void Mark(MacroBlockH264* mb, OverlayMem2Dv2* lum, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr);

  /** Dump the state variables of the macroblock to file.
  For debugging.
  @param  mb  : Macroblock to dump
  @param  filename  : File to write into
  @param  title     : Title of stored table data
  @return     : none.
  */
  static void Dump(MacroBlockH264* mb, char* filename, const char* title);

/// Constants.
public:
	static const int mbCodingOrderY[4][4];	///< Row
	static const int mbCodingOrderX[4][4];	///< Col
	static const int QPltoQPcMap[52];
	static const int Intra16x16ModeTable[24][3];

	/// Inter and Intra _mbPartPredMode values. For Inter, the _mbPartPredMode = _mb_type.
	static const int Inter_16x16		= 0;
	static const int Inter_16x8			= 1;
	static const int Inter_8x16			= 2;
	static const int Inter_8x8			= 3;
	static const int Inter_8x8_Ref	= 4;
	static const int Intra_4x4			= 8;
	static const int Intra_8x8			= 9;
	static const int Intra_16x16		= 10;
	/// Intra _intra4x4PredMode values.
	static const int Intra_4x4_Vert		          = 0;
	static const int Intra_4x4_Horiz	          = 1;
	static const int Intra_4x4_DC			          = 2;
	static const int Intra_4x4_Diag_Down_Left	  = 3;
	static const int Intra_4x4_Diag_Down_Right	= 4;
	static const int Intra_4x4_Vert_Right	      = 5;
	static const int Intra_4x4_Horiz_Down	      = 6;
	static const int Intra_4x4_Vert_Left	      = 7;
	static const int Intra_4x4_Horiz_Up	        = 8;
	/// Intra _intra16x16PredMode values.
	static const int Intra_16x16_Vert		= 0;
	static const int Intra_16x16_Horiz	= 1;
	static const int Intra_16x16_DC			= 2;
	static const int Intra_16x16_Plane	= 3;
	/// Intra _intraChrPredMode values.
	static const int Intra_Chr_DC			= 0;
	static const int Intra_Chr_Horiz	= 1;
	static const int Intra_Chr_Vert		= 2;
	static const int Intra_Chr_Plane	= 3;

	/// Motion vector array indices based on pred type.
	static const int _16x16		= 0;
	static const int _16x8_0	= 0;
	static const int _16x8_1	= 1;
	static const int _8x16_0	= 0;
	static const int _8x16_1	= 1;
	static const int _8x8_0		= 0;
	static const int _8x8_1		= 1;
	static const int _8x8_2		= 2;
	static const int _8x8_3		= 3;

/// Aux data members.
public:
	/// Relative pixel coords (top left) of this macroblock in a contiguous image mem. Each
	/// block in the macroblock describes its relative position from this offset.
	int			_offLumX;
	int			_offLumY;
	int			_offChrX;
	int			_offChrY;
	int			_mbIndex;		///< The index of this macroblock in the image space.
	int			_slice;			///< Slice number that this macroblock belongs to.

	/// References to this macroblock's neighbours that will be used for the predictions.
	/// These are related to ITU-T Rec. H.264 (03/2005) page 27 Section 6.4.6 and will
	/// have a NULL value if they are not available. E.g. Top row macroblocks will have
	/// all the _aboveMbxxx = NULL.
	MacroBlockH264*	_leftMb;				///< mbAddrA.
	MacroBlockH264*	_aboveLeftMb;		///< mbAddrD.
	MacroBlockH264*	_aboveMb;				///< mbAddrB.
	MacroBlockH264*	_aboveRightMb;	///< mbAddrC.

	/// Macroblock quantisation parameter derived from delta qp values.
	int			_mbQP;
  int     _mbEncQP; ///< QP used to store the _mbQP value that was used for the encoding.

	/// Motion vectors derived from motion vector difference values.
	int			_mvX[16];
	int			_mvY[16];

	/// The macroblock type coded value mb_type is constructed from combinations 
	/// of the following modes.
	int			_intraFlag;							///< Indicates the macroblock Intra/Inter status.
	int			_mbPartPredMode;				///< Macroblock partition prediction mode.
	int			_mbSubPartPredMode;			///< ...sub partition mode when partition mode is 8x8.
	int			_intra16x16PredMode;		///< Only for Intra_16x16 macroblocks = {0..3}.
	int			_intraChrPredMode;			///< For Intra_4x4 and Intra_16x16 macroblocks = {0..3}.
	int			_codedBlkPatternChr;
	int			_codedBlkPatternLum;

	/// Distortion-Rate optimisations require storing intermediate values. The arrays
	/// are directly addressable by _mbQP. Use an include flag to help with 
	/// heuristic elimination.
	int			_mvDistortion;		///< Total motion compensated distortion.
	int			_mvRate;					///< Total motion vector bit count.
	int			_distortion[87];	///< mbQP = {0...51} + {52..66 (Lum + Chr AC coeff)} + {67..70 (Chr DC)} + {71..86 (Lum DC)} extras.
	int			_rate[87];
	int			_include;

// Coded data members.
public:
	/// A flag to indicate that this macroblock has nothing to code and is skipped.
	int	_skip;

	/// The macroblock type defines the partitioning, prediction modes and the coded
	/// block patterns.
	int _mb_type;
	int _sub_mb_type;
	int _coded_blk_pattern;

	/// Differential quantisation parameter for lum coeffs. Chr quant parameter is
	/// derived from the lum qp.
	int _mb_qp_delta;

	/// Motion Vector Difference. From 1 to 16 vectors depending the partitions
	/// and sub partition sizes.
	int _mvdX[16];
	int _mvdY[16];

	/// Defined 4x4 blocks. Included are one lum 4x4 DC block and
	/// two chr 2x2 DC blocks. Overlays are created and the default
	/// block dimensions are 4x4 on instantiation.
	BlockH264	_lumDcBlk;				///< Index  = -1
	BlockH264 _lumBlk[4][4];		///<			  = 0...15
	BlockH264 _cbDcBlk;					///<				= 16	(NB: Chr instantiated as 4x4 and must be 2x2)
	BlockH264 _crDcBlk;					///<				= 17
	BlockH264 _cbBlk[2][2];			///<				= 18...21
	BlockH264 _crBlk[2][2];			///<				= 22...25
	/// Temporary working blocks.
	BlockH264	_lumDcBlkTmp;				///< Index  = -1
	BlockH264 _lumBlkTmp[4][4];		///<			  = 0...15
	BlockH264 _cbDcBlkTmp;				///<				= 16	(NB: Chr instantiated as 4x4 and must be 2x2)
	BlockH264 _crDcBlkTmp;				///<				= 17
	BlockH264 _cbBlkTmp[2][2];		///<				= 18...21
	BlockH264 _crBlkTmp[2][2];		///<				= 22...25
	/// Block references and their associated parameters to iterate
	/// through during encoding and decoding.
	MBH264_CODING_STRUCT	_blkParam[MBH264_NUM_BLKS];

  /// Extensions for Vector Quantisation.
  int _vq_flag;
  int _vq_distortion;     ///< Total VQ distortion (squared error) for the mb.
  int _vq_LumCode[4][4];  ///< VQ table address.
  int _vq_CbCode[2][2];
  int _vq_CrCode[2][2];

};// end class MacroBlockH264.

#endif	//_MACROBLOCKH264_H
========== END FILE: CodecUtils/MacroBlockH264.h ==========

========== BEGIN FILE: CodecUtils/MotionCompensatorH264ImplMultires.cpp ==========
Bundle entry: 79
Original bytes: 24343
Original SHA-256: 5ec7b4d68792555f1f47f9482e0fbad18bb7afd2f06ccf673a8af77acdb520ac
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionCompensatorH264ImplMultires

TAG						: MCH264IM

FILE NAME			: MotionCompensatorH264ImplMultires.cpp

DESCRIPTION		: A fast unrestricted motion compensator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionCompensator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionCompensatorH264ImplMultires.h"

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Only required at level 0 resolution.
#define MCH264IM_PADDING	3

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionCompensatorH264ImplMultires::MotionCompensatorH264ImplMultires(int range)
{
	// Parameters must remain const for the life time of this instantiation.
	_imgWidth						= 0;				// Width of the ref images. 
	_imgHeight					= 0;				// Height of the ref images.
	_chrWidth						= 0;
	_chrHeight					= 0;
	_macroBlkWidth			= 0;				// Width of the motion block.
	_macroBlkHeight			= 0;				// Height of the motion block.
	_chrMacroBlkWidth		= 0;
	_chrMacroBlkHeight	= 0;
	_range							= range;
	_refSize						= 0;

	_pRefLum						= NULL;		// References to the images at creation.
	_pRefChrU						= NULL;
	_pRefChrV						= NULL;

	_pRefLumOver				= NULL;		// Overlays.
	_pRefChrUOver				= NULL;
	_pRefChrVOver				= NULL;

	_pExtTmpLum					= NULL;		// Extended boundary temp images.
	_pExtTmpLumOver			= NULL;
	_extLumWidth				= 0;
	_extLumHeight				= 0;
	_pExtTmpChrU				= NULL;
	_pExtTmpChrUOver		= NULL;
	_pExtTmpChrV				= NULL;
	_pExtTmpChrVOver		= NULL;
	_extChrWidth				= 0;
	_extChrHeight				= 0;

	_pMBlk							= NULL;
	_pMBlkOver					= NULL;

}//end constructor.

MotionCompensatorH264ImplMultires::~MotionCompensatorH264ImplMultires(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionCompensator Interface. 
--------------------------------------------------------------------------
*/

int MotionCompensatorH264ImplMultires::Create(void* ref, 
																							int imgWidth,			 int imgHeight, 
																							int macroBlkWidth, int macroBlkHeight)
{
	// Clean out old mem.
	Destroy();

	if(ref == NULL)
		return(0);

	// Parameters must remain const for the life time of this instantiation.
	_imgWidth						= imgWidth;				// Width of the ref images. 
	_imgHeight					= imgHeight;			// Height of the ref images.
	_chrWidth						= imgWidth/2;			// YUV 420.
	_chrHeight					= imgHeight/2;
	_macroBlkWidth			= macroBlkWidth;	// Width of the motion block.
	_macroBlkHeight			= macroBlkHeight;	// Height of the motion block.
	_chrMacroBlkWidth		= macroBlkWidth/2;
	_chrMacroBlkHeight	= macroBlkHeight/2;
	_refSize						= (_imgWidth * _imgHeight) + 2*(_chrWidth * _chrHeight);

	// Assign the head of contiguous mem to the lum ref.
	_pRefLum = (short *)ref;
	_pRefChrU = &_pRefLum[_imgWidth * _imgHeight];
	_pRefChrV = &_pRefLum[(_imgWidth * _imgHeight) + (_chrWidth * _chrHeight)];

	// --------------- Configure ref overlays --------------------------------
	// Overlay the reference and set to the motion block size.  
	_pRefLumOver	= new OverlayMem2Dv2( (void *)_pRefLum, 
																		_imgWidth, 
																		_imgHeight, 
																		_macroBlkWidth, 
																		_macroBlkHeight );
	_pRefChrUOver	= new OverlayMem2Dv2( (void *)_pRefChrU, 
																		_chrWidth, 
																		_chrHeight, 
																		_chrMacroBlkWidth, 
																		_chrMacroBlkHeight );
	_pRefChrVOver	= new OverlayMem2Dv2( (void *)_pRefChrV, 
																		_chrWidth, 
																		_chrHeight, 
																		_chrMacroBlkWidth, 
																		_chrMacroBlkHeight );
	if( (_pRefLumOver == NULL)||(_pRefChrUOver == NULL)||(_pRefChrVOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pRefLumOver...

	// --------------- Create extended boundary mem ---------------------------
	// Create the new extended boundary temp ref into _pExtTmpLum, _pExtTmpChrU
	// and _pExtTmpChrV. These are required before placing overlays on them.

	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefLum, 
																			_imgWidth,						
																			_imgHeight, 
																			_range + 1 + MCH264IM_PADDING,	///< Extend left and right by...
																			_range + 1 + MCH264IM_PADDING,	///< Extend top and bottom by...
																			(void **)(&_pExtTmpLum)) )			///< Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extLumWidth	= _imgWidth + (_range + 1 + MCH264IM_PADDING)*2;
	_extLumHeight	= _imgHeight + (_range + 1 + MCH264IM_PADDING)*2;

	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefChrU, 
																			_chrWidth,						
																			_chrHeight, 
																			(_range/2) + 2, // Extend left and right by...
																			(_range/2) + 2,	// Extend top and bottom by...
																			(void **)(&_pExtTmpChrU)) )	// Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefChrV, 
																			_chrWidth,						
																			_chrHeight, 
																			(_range/2) + 2, // Extend left and right by...
																			(_range/2) + 2,	// Extend top and bottom by...
																			(void **)(&_pExtTmpChrV)) )	// Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extChrWidth	= _chrWidth + ((_range/2) + 2)*2;
	_extChrHeight	= _chrHeight + ((_range/2) + 2)*2;

	// --------------- Configure temp extended ref overlays -------------------------
	// Overlay the extended temp ref and set to the whole image block size. In use 
	// call the SetOverlayDim() method to switch the block size.

	_pExtTmpLumOver = new OverlayExtMem2Dv2(_pExtTmpLum, 
																				_extLumWidth,		// new mem width.
																				_extLumHeight,	// new mem height.
																				_imgWidth,			// block width.
																				_imgHeight,			// block height.
																				_range + 1 + MCH264IM_PADDING,			// boundary width.
																				_range + 1 + MCH264IM_PADDING);		// boundary height.

	_pExtTmpChrUOver = new OverlayExtMem2Dv2(	_pExtTmpChrU, 
																					_extChrWidth,		// new mem width.
																					_extChrHeight,	// new mem height.
																					_chrWidth,			// block width.
																					_chrHeight,			// block height.
																					(_range/2) + 2,	// boundary width.
																					(_range/2) + 2);// boundary height.

	_pExtTmpChrVOver = new OverlayExtMem2Dv2(	_pExtTmpChrV, 
																					_extChrWidth,		// new mem width.
																					_extChrHeight,	// new mem height.
																					_chrWidth,			// block width.
																					_chrHeight,			// block height.
																					(_range/2) + 2,	// boundary width.
																					(_range/2) + 2);// boundary height.

	if( (_pExtTmpLumOver == NULL)||(_pExtTmpChrUOver == NULL)||(_pExtTmpChrVOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pRefLumOver...

	// Alloc some temp mem and overlay it to use for half pel motion compensation. 
	// The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																				_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	return(1);
}//end Create.

void	MotionCompensatorH264ImplMultires::Reset(void)
{
	memset((void *)_pRefLum, 0, _refSize * sizeof(short));
}//end Reset.

void MotionCompensatorH264ImplMultires::Destroy(void)
{
	if(_pRefLumOver != NULL)
		delete _pRefLumOver;
	_pRefLumOver = NULL;

	if(_pRefChrUOver != NULL)
		delete _pRefChrUOver;
	_pRefChrUOver = NULL;

	if(_pRefChrVOver != NULL)
		delete _pRefChrVOver;
	_pRefChrVOver = NULL;

	_pRefLum		= NULL;
	_pRefChrU		= NULL;
	_pRefChrV		= NULL;

	// Delete extended temp overlays before the underlying mem.
	if(_pExtTmpLumOver != NULL)
		delete _pExtTmpLumOver;
	_pExtTmpLumOver = NULL;
	if(_pExtTmpChrUOver != NULL)
		delete _pExtTmpChrUOver;
	_pExtTmpChrUOver = NULL;
	if(_pExtTmpChrVOver != NULL)
		delete _pExtTmpChrVOver;
	_pExtTmpChrVOver = NULL;

	// Delete extended temp ref mem.
	if(_pExtTmpLum != NULL)
		delete[] _pExtTmpLum;
	_pExtTmpLum = NULL;
	if(_pExtTmpChrU != NULL)
		delete[] _pExtTmpChrU;
	_pExtTmpChrU = NULL;
	if(_pExtTmpChrV != NULL)
		delete[] _pExtTmpChrV;
	_pExtTmpChrV = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;
}//end Destroy.

/** Motion compensate to the reference.
Do the compensation with the block sizes and image sizes defined in
the implementation and set in Create().
@param pMotionList	: The list of motion vectors.
@return							: None.
*/
void MotionCompensatorH264ImplMultires::Compensate(void* pMotionList)
{
	// Get the motion vector list to work with. Assume SIMPLE2D type list.
	VectorStructList* pL			= (VectorStructList *)pMotionList;
	int								listLen = pL->GetLength();
	int								vecPos  = 0;

	// None to compensate or wrong type.
	if( (listLen == 0)||(pL->GetType() != VectorStructList::SIMPLE2D) )
		return;

  // Dump the entire ref into the tmp so that vectors can be taken 
  // from the tmp and written back to the ref. 
	PrepareForSingleVectorMode();

  // Do compensation in the sequence order from tmp to ref.
	int mvx	= 0;
	int mvy	= 0;
  for(int m = 0; m < _imgHeight; m += _macroBlkHeight)
	  for(int n = 0; n < _imgWidth; n += _macroBlkWidth)
  {
		mvx = pL->GetSimpleElement(vecPos, 0);
		mvy = pL->GetSimpleElement(vecPos, 1);
		vecPos++;

		Compensate(n, m, mvx, mvy);

  }//end for m & n...

}//end Compensate.

/** Prepare the ref for single motion vector compensation mode.
Should be used to copy the ref into a temp location from which to
do the compensation to the ref. Prevents interference and double
compensation.
@return : none.
*/
void MotionCompensatorH264ImplMultires::PrepareForSingleVectorMode(void)
{
	// Write the ref to the temp ref and fill its extended boundary. The 
	// centre part of _pExtTmpLumOver is copied from _pRefLumOver before 
	// filling the boundary.

	// Set pos and block size to whole image for temp and ref.
	_pExtTmpLumOver->SetOrigin(0, 0);
	_pExtTmpLumOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pRefLumOver->SetOrigin(0, 0);
	_pRefLumOver->SetOverlayDim(_imgWidth, _imgHeight);
	// Fill and extend boundary.
	_pExtTmpLumOver->Write(*_pRefLumOver);
	_pExtTmpLumOver->FillBoundaryProxy();
	// Set block sizes back to the macroblock.
	_pExtTmpLumOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);
	_pRefLumOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	_pExtTmpChrUOver->SetOrigin(0, 0);
	_pExtTmpChrUOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pRefChrUOver->SetOrigin(0, 0);
	_pRefChrUOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pExtTmpChrUOver->Write(*_pRefChrUOver);
	_pExtTmpChrUOver->FillBoundaryProxy();
	_pExtTmpChrUOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);
	_pRefChrUOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);

	_pExtTmpChrVOver->SetOrigin(0, 0);
	_pExtTmpChrVOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pRefChrVOver->SetOrigin(0, 0);
	_pRefChrVOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pExtTmpChrVOver->Write(*_pRefChrVOver);
	_pExtTmpChrVOver->FillBoundaryProxy();
	_pExtTmpChrVOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);
	_pRefChrVOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);

}//end PrepareForSingleVectorMode.

/** Motion compensate a single vector to the reference.
Do the compensation with the block sizes and image sizes defined in
the implementation and set in Create(). The vector coords are in 
half pel units for this implementation. NOTE: The temp image must
hold a copy of the ref BEFORE using this method and is should be done
in PrepareForSingleVectorMode().
@param tlx	: Top left x coord of block.
@param tly	: Top left y coord of block.
@param mvx	: X coord of the motion vector.
@param mvy	: Y coord of the motion vector.
@return			: None.
*/
void MotionCompensatorH264ImplMultires::Compensate(int tlx, int tly, int mvx, int mvy)
{
	// Don't bother if the vector is zero.
	if( mvx || mvy )
  {
    // Lum first.
    int motion_x			= mvx / 2;
    int motion_y			= mvy / 2;
    int half_motion_x	= mvx % 2;
    int half_motion_y	= mvy % 2;

 		// Position the overlays. The vector is always assumed to fall within
		// the extended img bounds and relies on the range not to generate
		// invalid vectors.
		_pRefLumOver->SetOrigin(tlx, tly);
		_pExtTmpLumOver->SetOrigin(tlx+motion_x, tly+ motion_y);
		if( !half_motion_x && !half_motion_y )	// No half pel implies straight copy.
			_pRefLumOver->Write(*_pExtTmpLumOver);
		else
		{
			// Read the compensated block into a work area.
			_pExtTmpLumOver->HalfReadv2(*_pMBlkOver, half_motion_x, half_motion_y);
			// Write it to the ref.
			_pRefLumOver->Write(*_pMBlkOver);
		}//end else...

    // Chr second.
    int offvecx	= tlx/2;
    int offvecy	= tly/2;
		// Quarter pel is rounded to half pel.
    half_motion_x	= mvx % 4;
		if(half_motion_x < 0)
			half_motion_x = -1;
		else if(half_motion_x > 0)
			half_motion_x = 1;
    half_motion_y	= mvy % 4;
		if(half_motion_y < 0)
			half_motion_y = -1;
		else if(half_motion_y > 0)
			half_motion_y = 1;
    motion_x = mvx / 4;
    motion_y = mvy / 4;

 		// Position the overlays. The vector is always assumed to fall within
		// the extended img bounds and relies on the range not to generate
		// invalid vectors.
		_pRefChrUOver->SetOrigin(offvecx, offvecy);
		_pRefChrVOver->SetOrigin(offvecx, offvecy);
		_pExtTmpChrUOver->SetOrigin(offvecx+motion_x, offvecy+ motion_y);
		_pExtTmpChrVOver->SetOrigin(offvecx+motion_x, offvecy+ motion_y);
		if( !half_motion_x && !half_motion_y )	// No half pel implies straight copy.
		{
			_pRefChrUOver->Write(*_pExtTmpChrUOver);
			_pRefChrVOver->Write(*_pExtTmpChrVOver);
		}//end if !...
		else
		{
			/// Read the compensated block into a work area and write it to the ref.
			_pExtTmpChrUOver->HalfRead(*_pMBlkOver, half_motion_x, half_motion_y);
			_pRefChrUOver->Write(*_pMBlkOver);
			_pExtTmpChrVOver->HalfRead(*_pMBlkOver, half_motion_x, half_motion_y);
			_pRefChrVOver->Write(*_pMBlkOver);
		}//end else...
  }//end if mvx...

}//end Compensate.

/*
--------------------------------------------------------------------------------------
	Redundant code.
--------------------------------------------------------------------------------------
*/
/*
void MotionCompensatorH264ImplMultires::Compensate(int tlx, int tly, int mvx, int mvy)
{
	int x,y;

	// Extract vector and copy.
	if( mvx || mvy )
  {
    // Lum first.
    int motion_x			= mvx / 2;
    int motion_y			= mvy / 2;
    int half_motion_x	= mvx % 2;
    int half_motion_y	= mvy % 2;

   // Treat the half pel conditions differently.
    if(!half_motion_y && !half_motion_x) // Both zero.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row = tly + y;
        int c_row = tly + y + motion_y;
        if(c_row < 0)
          c_row = 0;
        if(c_row >= _imgHeight)
          c_row = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col = tlx + x;
          int c_col = tlx + x + motion_x;
          if(c_col < 0)
            c_col = 0;
          if(c_col >= _imgWidth)
            c_col = _imgWidth - 1;
          _refLum[r_row][r_col] = _tmpLum[c_row][c_col];
        }//end for x...
      }//end for y...
    }//end if half_motion_y...
    else if(half_motion_y && half_motion_x) // Diagonals.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row = tly + y;
        int c_row1 = tly + y + motion_y;
        int c_row2 = tly + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _imgHeight)
          c_row1 = _imgHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _imgHeight)
          c_row2 = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col	= tlx + x;
          int c_col1 = tlx + x + motion_x;
          int c_col2 = tlx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _imgWidth)
            c_col1 = _imgWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _imgWidth)
            c_col2 = _imgWidth - 1;
          _refLum[r_row][r_col] = (_tmpLum[c_row1][c_col1] + _tmpLum[c_row1][c_col2] +
																 _tmpLum[c_row2][c_col1] + _tmpLum[c_row2][c_col2] + 2)/4;
        }//end for x...
      }//end for y...
    }//end else if half_motion_y...
    else // Linear motion.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row	= tly + y;
        int c_row1 = tly + y + motion_y;
        int c_row2 = tly + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _imgHeight)
          c_row1 = _imgHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _imgHeight)
          c_row2 = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col	= tlx + x;
          int c_col1 = tlx + x + motion_x;
          int c_col2 = tlx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _imgWidth)
            c_col1 = _imgWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _imgWidth)
            c_col2 = _imgWidth - 1;
          _refLum[r_row][r_col] = (_tmpLum[c_row1][c_col1] + _tmpLum[c_row2][c_col2] + 1)/2;
        }//end for x...
      }//end for y...
    }//end else...

    // Chr second.
    int offvecx	= tlx/2;
    int offvecy	= tly/2;
    half_motion_x			= motion_x % 2;
    half_motion_y			= motion_y % 2;
    motion_x					= motion_x / 2;
    motion_y					= motion_y / 2;
    // Treat the half pel conditions differently.
    if(!half_motion_y && !half_motion_x) // Both zero.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row = offvecy + y + motion_y;
        if(c_row < 0)
          c_row = 0;
        if(c_row >= _chrHeight)
          c_row = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col = offvecx + x + motion_x;
          if(c_col < 0)
            c_col = 0;
          if(c_col >= _chrWidth)
            c_col = _chrWidth - 1;
          _refChrU[r_row][r_col] = _tmpChrU[c_row][c_col];
          _refChrV[r_row][r_col] = _tmpChrV[c_row][c_col];
        }//end for x...
      }//end for y...
    }//end if half_motion_y...
    else if(half_motion_y && half_motion_x) // Diagonals.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row1 = offvecy + y + motion_y;
        int c_row2 = offvecy + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _chrHeight)
          c_row1 = _chrHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _chrHeight)
          c_row2 = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col1 = offvecx + x + motion_x;
          int c_col2 = offvecx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _chrWidth)
            c_col1 = _chrWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _chrWidth)
            c_col2 = _chrWidth - 1;
          _refChrU[r_row][r_col] = (_tmpChrU[c_row1][c_col1] + _tmpChrU[c_row1][c_col2] +
																	_tmpChrU[c_row2][c_col1] + _tmpChrU[c_row2][c_col2] + 2)/4;
          _refChrV[r_row][r_col] = (_tmpChrV[c_row1][c_col1] + _tmpChrV[c_row1][c_col2] +
																	_tmpChrV[c_row2][c_col1] + _tmpChrV[c_row2][c_col2] + 2)/4;
        }//end for x...
      }//end for y...
    }//end else if half_motion_y...
    else // Linear motion.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row1 = offvecy + y + motion_y;
        int c_row2 = offvecy + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _chrHeight)
          c_row1 = _chrHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _chrHeight)
          c_row2 = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col1 = offvecx + x + motion_x;
          int c_col2 = offvecx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _chrWidth)
            c_col1 = _chrWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _chrWidth)
            c_col2 = _chrWidth - 1;
          _refChrU[r_row][r_col] = (_tmpChrU[c_row1][c_col1] + _tmpChrU[c_row2][c_col2] + 1)/2;
          _refChrV[r_row][r_col] = (_tmpChrV[c_row1][c_col1] + _tmpChrV[c_row2][c_col2] + 1)/2;
        }//end for x...
      }//end for y...
    }//end else...
  }//end if mvx...

}//end Compensate.
*/
========== END FILE: CodecUtils/MotionCompensatorH264ImplMultires.cpp ==========

========== BEGIN FILE: CodecUtils/MotionCompensatorH264ImplMultires.h ==========
Bundle entry: 80
Original bytes: 5908
Original SHA-256: 16bfefdc6bf0ffcda08109bc27798bee53c98a88f74f63fdf91691367c5ff0fe
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionCompensatorH264ImplMultires

TAG						: MCH264IM

FILE NAME			: MotionCompensatorH264ImplMultires.h

DESCRIPTION		: A fast unrestricted motion compensator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionCompensator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONCOMPENSATORH264IMPLMULTIRES_H
#define _MOTIONCOMPENSATORH264IMPLMULTIRES_H

#include "IMotionCompensator.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionCompensatorH264ImplMultires : public IMotionCompensator
{
	// Construction.
	public:

		MotionCompensatorH264ImplMultires(int range);
		virtual ~MotionCompensatorH264ImplMultires(void);

	// IMotionCompensator Interface.
	public:
		
		virtual int	Create(	void* ref, 
												int imgWidth,	int imgHeight, 
												int macroBlkWidth, int macroBlkHeight);
		virtual void	Destroy(void);
		virtual void	Reset(void);

		/** Motion compensate to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create().
		@param pMotionList	: The list of motion vectors.
		@return							: None.
		*/
		virtual void Compensate(void* pMotionList);

		/** Motion compensate a single vector to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create(). The vector coords are in 
		half pel units for this implementation. NOTE: The temp image must
		hold a copy of the ref BEFORE using this method and is should be done
		in PrepareForSingleVectorMode().
		@param tlx	: Top left x coord of block.
		@param tly	: Top left y coord of block.
		@param mvx	: X coord of the motion vector.
		@param mvy	: Y coord of the motion vector.
		@return			: None.
		*/
		virtual void Compensate(int tlx, int tly, int mvx, int mvy);

		/** Prepare the ref for single motion vector compensation mode.
		Should be used to copy the ref into a temp location from which to
		do the compensation to the ref. Prevents interference and double
		compensation.
		@return : none.
		*/
		virtual void PrepareForSingleVectorMode(void);

	/// Local methods.
	protected:

		/// Parameters must remain const for the life time of this instantiation.
		int	_imgWidth;				// Width of the ref images. 
		int	_imgHeight;				// Height of the ref images.
		int _chrWidth;
		int _chrHeight;
		int	_macroBlkWidth;		// Width of the motion block.
		int	_macroBlkHeight;	// Height of the motion block.
		int _chrMacroBlkWidth;
		int _chrMacroBlkHeight;
		int _range;						// Max range of the motion [-_range ... (_range-1)].

		int _refSize;					// Total size (in mcisType) of the contiguous Lum, ChrU, ChrV.
		/// Ref image holders.
		short*		_pRefLum;		// References to the images at creation.
		short*		_pRefChrU;
		short*		_pRefChrV;

		// Overlays to the ref image.
		OverlayMem2Dv2*	_pRefLumOver;
		OverlayMem2Dv2*	_pRefChrUOver;
		OverlayMem2Dv2*	_pRefChrVOver;

		// Extended temp ref mem created by ExtendBoundary() calls for each colour
		// component and an extended boundary overlay for each.
		short*							_pExtTmpLum;
		OverlayExtMem2Dv2*	_pExtTmpLumOver;
		int									_extLumWidth;
		int									_extLumHeight;
		short*							_pExtTmpChrU;
		OverlayExtMem2Dv2*	_pExtTmpChrUOver;
		short*							_pExtTmpChrV;
		OverlayExtMem2Dv2*	_pExtTmpChrVOver;
		int									_extChrWidth;
		int									_extChrHeight;

		// A work block.
		short*					_pMBlk;
		OverlayMem2Dv2* _pMBlkOver;
};//end MotionCompensatorH264ImplMultires.


#endif	// _MOTIONCOMPENSATORH264IMPLMULTIRES_H
========== END FILE: CodecUtils/MotionCompensatorH264ImplMultires.h ==========

========== BEGIN FILE: CodecUtils/MotionCompensatorH264ImplStd.cpp ==========
Bundle entry: 81
Original bytes: 24827
Original SHA-256: 5f15047bbdc1495a296635100223e7cc83ccdd2b2ce09d9eb3e1c539af7604e9
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionCompensatorH264ImplStd

TAG						: MCH264IS

FILE NAME			: MotionCompensatorH264ImplStd.cpp

DESCRIPTION		: A fast unrestricted motion compensator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionCompensator interface. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionCompensatorH264ImplStd.h"

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Only required at level 0 resolution.
#define MCH264IS_PADDING	4

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MCH264IS_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionCompensatorH264ImplStd::MotionCompensatorH264ImplStd(int range)
{
	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth						= 0;			///< Width of the ref images. 
	_imgHeight					= 0;			///< Height of the ref images.
	_chrWidth						= 0;
	_chrHeight					= 0;
	_macroBlkWidth			= 0;			///< Width of the motion block.
	_macroBlkHeight			= 0;		  ///< Height of the motion block.
	_chrMacroBlkWidth		= 0;
	_chrMacroBlkHeight	= 0;
	_range							= range;
	_refSize						= 0;
  _invalid            = 0;      ///< Invalidate the compensation to force copying on the next compensated vector.

	_pRefLum						= NULL;		///< References to the images at creation.
	_pRefChrU						= NULL;
	_pRefChrV						= NULL;

	_pRefLumOver				= NULL;		///< Overlays.
	_pRefChrUOver				= NULL;
	_pRefChrVOver				= NULL;
	
	_pExtTmpLum					= NULL;		///< Extended boundary temp images.
	_pExtTmpLumOver			= NULL;
	_extLumWidth				= 0;
	_extLumHeight				= 0;
	_pExtTmpChrU				= NULL;
	_pExtTmpChrUOver		= NULL;
	_pExtTmpChrV				= NULL;
	_pExtTmpChrVOver		= NULL;
	_extChrWidth				= 0;
	_extChrHeight				= 0;

	_pMBlk							= NULL;
	_pMBlkOver					= NULL;

}//end constructor.

MotionCompensatorH264ImplStd::~MotionCompensatorH264ImplStd(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionCompensator Interface. 
--------------------------------------------------------------------------
*/

int MotionCompensatorH264ImplStd::Create(	void* ref, 
																					int imgWidth,			 int imgHeight, 
																					int macroBlkWidth, int macroBlkHeight)
{
	/// Clean out old mem.
	Destroy();

	if(ref == NULL)
		return(0);

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth						= imgWidth;				///< Width of the ref images. 
	_imgHeight					= imgHeight;			///< Height of the ref images.
	_chrWidth						= imgWidth/2;			///< YUV 420 only.
	_chrHeight					= imgHeight/2;
	_macroBlkWidth			= macroBlkWidth;	///< Width of the motion block.
	_macroBlkHeight			= macroBlkHeight;	///< Height of the motion block.
	_chrMacroBlkWidth		= macroBlkWidth/2;
	_chrMacroBlkHeight	= macroBlkHeight/2;
	_refSize						= (_imgWidth * _imgHeight) + 2*(_chrWidth * _chrHeight);

	/// Assign the head of contiguous mem to the lum ref.
	_pRefLum = (short *)ref;
	_pRefChrU = &_pRefLum[_imgWidth * _imgHeight];
	_pRefChrV = &_pRefLum[(_imgWidth * _imgHeight) + (_chrWidth * _chrHeight)];

	/// --------------- Configure ref overlays --------------------------------
	/// Overlay the reference and set to the motion block size.  
	_pRefLumOver	= new OverlayMem2Dv2( (short *)_pRefLum, 
																			_imgWidth, 
																			_imgHeight, 
																			_macroBlkWidth, 
																			_macroBlkHeight );
	_pRefChrUOver	= new OverlayMem2Dv2( (short *)_pRefChrU, 
																			_chrWidth, 
																			_chrHeight, 
																			_chrMacroBlkWidth, 
																			_chrMacroBlkHeight );
	_pRefChrVOver	= new OverlayMem2Dv2( (short *)_pRefChrV, 
																			_chrWidth, 
																			_chrHeight, 
																			_chrMacroBlkWidth, 
																			_chrMacroBlkHeight );
	if( (_pRefLumOver == NULL)||(_pRefChrUOver == NULL)||(_pRefChrVOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pRefLumOver...

	/// --------------- Create extended boundary mem ---------------------------
	/// Create the new extended boundary temp ref into _pExtTmpLum, _pExtTmpChrU
	/// and _pExtTmpChrV. These are required before placing overlays on them.

	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefLum, 
																				_imgWidth,						
																				_imgHeight, 
																				_range + 1 + MCH264IS_PADDING,	///< Extend left and right by...
																				_range + 1 + MCH264IS_PADDING,	///< Extend top and bottom by...
																				(void **)(&_pExtTmpLum)) )			///< Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extLumWidth	= _imgWidth + (_range + 1 + MCH264IS_PADDING)*2;
	_extLumHeight	= _imgHeight + (_range + 1 + MCH264IS_PADDING)*2;

	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefChrU, 
																				_chrWidth,						
																				_chrHeight, 
																				(_range/2) + 4, ///< Extend left and right by...
																				(_range/2) + 4,	///< Extend top and bottom by...
																				(void **)(&_pExtTmpChrU)) )	///< Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefChrV, 
																				_chrWidth,						
																				_chrHeight, 
																				(_range/2) + 4, ///< Extend left and right by...
																				(_range/2) + 4,	///< Extend top and bottom by...
																				(void **)(&_pExtTmpChrV)) )	///< Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extChrWidth	= _chrWidth + ((_range/2) + 4)*2;
	_extChrHeight	= _chrHeight + ((_range/2) + 4)*2;

	/// --------------- Configure temp extended ref overlays -------------------------
	/// Overlay the extended temp ref and set to the whole image block size. In use 
	/// call the SetOverlayDim() method to switch the block size.

	_pExtTmpLumOver = new OverlayExtMem2Dv2(_pExtTmpLum, 
																					_extLumWidth,		///< new mem width.
																					_extLumHeight,	///< new mem height.
																					_imgWidth,			///< block width.
																					_imgHeight,			///< block height.
																					_range + 1 + MCH264IS_PADDING,		///< boundary width.
																					_range + 1 + MCH264IS_PADDING);		///< boundary height.

	_pExtTmpChrUOver = new OverlayExtMem2Dv2(	_pExtTmpChrU, 
																						_extChrWidth,		///< new mem width.
																						_extChrHeight,	///< new mem height.
																						_chrWidth,			///< block width.
																						_chrHeight,			///< block height.
																						(_range/2) + 4,	///< boundary width.
																						(_range/2) + 4);///< boundary height.

	_pExtTmpChrVOver = new OverlayExtMem2Dv2(	_pExtTmpChrV, 
																						_extChrWidth,		///< new mem width.
																						_extChrHeight,	///< new mem height.
																						_chrWidth,			///< block width.
																						_chrHeight,			///< block height.
																						(_range/2) + 4,	///< boundary width.
																						(_range/2) + 4);///< boundary height.

	if( (_pExtTmpLumOver == NULL)||(_pExtTmpChrUOver == NULL)||(_pExtTmpChrVOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pRefLumOver...

	/// Alloc some temp mem and overlay it to use for quarter pel motion compensation. 
	/// The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	return(1);
}//end Create.

void	MotionCompensatorH264ImplStd::Reset(void)
{
	memset((void *)_pRefLum, 0, _refSize * sizeof(short));
}//end Reset.

void MotionCompensatorH264ImplStd::Destroy(void)
{
	if(_pRefLumOver != NULL)
		delete _pRefLumOver;
	_pRefLumOver = NULL;

	if(_pRefChrUOver != NULL)
		delete _pRefChrUOver;
	_pRefChrUOver = NULL;

	if(_pRefChrVOver != NULL)
		delete _pRefChrVOver;
	_pRefChrVOver = NULL;

	_pRefLum		= NULL;
	_pRefChrU		= NULL;
	_pRefChrV		= NULL;

	/// Delete extended temp overlays before the underlying mem.
	if(_pExtTmpLumOver != NULL)
		delete _pExtTmpLumOver;
	_pExtTmpLumOver = NULL;
	if(_pExtTmpChrUOver != NULL)
		delete _pExtTmpChrUOver;
	_pExtTmpChrUOver = NULL;
	if(_pExtTmpChrVOver != NULL)
		delete _pExtTmpChrVOver;
	_pExtTmpChrVOver = NULL;

	/// Delete extended temp ref mem.
	if(_pExtTmpLum != NULL)
		delete[] _pExtTmpLum;
	_pExtTmpLum = NULL;
	if(_pExtTmpChrU != NULL)
		delete[] _pExtTmpChrU;
	_pExtTmpChrU = NULL;
	if(_pExtTmpChrV != NULL)
		delete[] _pExtTmpChrV;
	_pExtTmpChrV = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;
}//end Destroy.

/** Motion compensate to the reference.
Do the compensation with the block sizes and image sizes defined in
the implementation and set in Create().
@param pMotionList	: The list of motion vectors.
@return							: None.
*/
void MotionCompensatorH264ImplStd::Compensate(void* pMotionList)
{
	/// Get the motion vector list to work with. Assume SIMPLE2D type list.
	VectorStructList* pL			= (VectorStructList *)pMotionList;
	int								listLen = pL->GetLength();
	int								vecPos  = 0;

	/// None to compensate or wrong type.
	if( (listLen == 0)||(pL->GetType() != VectorStructList::SIMPLE2D) )
		return;

  /// Dump the entire ref into the tmp so that vectors can be taken 
  /// from the tmp and written back to the ref. 
	PrepareForSingleVectorMode();

  /// Do compensation in the sequence order from tmp to ref.
	int mvx	= 0;
	int mvy	= 0;
  for(int m = 0; m < _imgHeight; m += _macroBlkHeight)
	  for(int n = 0; n < _imgWidth; n += _macroBlkWidth)
  {
		mvx = pL->GetSimpleElement(vecPos, 0);
		mvy = pL->GetSimpleElement(vecPos, 1);
		vecPos++;

		Compensate(n, m, mvx, mvy);

  }//end for m & n...

}//end Compensate.

/** Prepare the ref for single motion vector compensation mode.
Should be used to copy the ref into a temp location from which to
do the compensation to the ref. Prevents interference and double
compensation.
@return : none.
*/
void MotionCompensatorH264ImplStd::PrepareForSingleVectorMode(void)
{
	/// Write the ref to the temp ref and fill its extended boundary. The 
	/// centre part of _pExtTmpLumOver is copied from _pRefLumOver before 
	/// filling the boundary.

	/// Set pos and block size to whole image for temp and ref.
	_pExtTmpLumOver->SetOrigin(0, 0);
	_pExtTmpLumOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pRefLumOver->SetOrigin(0, 0);
	_pRefLumOver->SetOverlayDim(_imgWidth, _imgHeight);
	/// Fill and extend boundary.
	_pExtTmpLumOver->Write(*_pRefLumOver);
	_pExtTmpLumOver->FillBoundaryProxy();
	/// Set block sizes back to the macroblock.
	_pExtTmpLumOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);
	_pRefLumOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	_pExtTmpChrUOver->SetOrigin(0, 0);
	_pExtTmpChrUOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pRefChrUOver->SetOrigin(0, 0);
	_pRefChrUOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pExtTmpChrUOver->Write(*_pRefChrUOver);
	_pExtTmpChrUOver->FillBoundaryProxy();
	_pExtTmpChrUOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);
	_pRefChrUOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);

	_pExtTmpChrVOver->SetOrigin(0, 0);
	_pExtTmpChrVOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pRefChrVOver->SetOrigin(0, 0);
	_pRefChrVOver->SetOverlayDim(_chrWidth, _chrHeight);
	_pExtTmpChrVOver->Write(*_pRefChrVOver);
	_pExtTmpChrVOver->FillBoundaryProxy();
	_pExtTmpChrVOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);
	_pRefChrVOver->SetOverlayDim(_chrMacroBlkWidth, _chrMacroBlkHeight);

}//end PrepareForSingleVectorMode.

/** Motion compensate a single vector to the reference.
Do the compensation with the block sizes and image sizes defined in
the implementation and set in Create(). The vector coords are in 
quarter pel units for this implementation. NOTE: The temp image must
hold a copy of the ref BEFORE using this method and is should be done
in PrepareForSingleVectorMode().
@param tlx	: Top left x coord of block.
@param tly	: Top left y coord of block.
@param mvx	: X coord of the motion vector in 1/4 pel units.
@param mvy	: Y coord of the motion vector in 1/4 pel units.
@return			: None.
*/
void MotionCompensatorH264ImplStd::Compensate(int tlx, int tly, int mvx, int mvy)
{
	/// Don't bother if the vector is zero unless invalidated.
	if( mvx || mvy || _invalid )
  {
    /// Lum first.
    _pMBlkOver->SetOverlayDim(16,16);

    int motion_x			= mvx / 4;	///< Convert quarter pel units to full and quarter offsets.
    int motion_y			= mvy / 4;
    int quarter_motion_x	= mvx % 4;
    int quarter_motion_y	= mvy % 4;

 		/// Position the overlays. The vector is always assumed to fall within
		/// the extended img bounds and relies on the range not to generate
		/// invalid vectors.
		_pRefLumOver->SetOrigin(tlx, tly);
		_pExtTmpLumOver->SetOrigin(tlx+motion_x, tly+ motion_y);
		if( !quarter_motion_x && !quarter_motion_y )	///< No quarter pel implies straight copy.
			_pRefLumOver->Write(*_pExtTmpLumOver);
		else
		{
			/// Read the compensated block into a work area.
			_pExtTmpLumOver->QuarterRead(*_pMBlkOver, quarter_motion_x, quarter_motion_y);
			/// Write it to the ref.
			_pRefLumOver->Write(*_pMBlkOver);
		}//end else...

    /// Chr second.
    _pMBlkOver->SetOverlayDim(8,8);

    int offvecx	= tlx/2;
    int offvecy	= tly/2;
		int eighth_motion_x = mvx % 8;
		int eighth_motion_y = mvy % 8;
    motion_x = mvx / 8;
    motion_y = mvy / 8;

 		/// Position the overlays. The vector is always assumed to fall within
		/// the extended img bounds and relies on the range not to generate
		/// invalid vectors.
		_pRefChrUOver->SetOrigin(offvecx, offvecy);
		_pRefChrVOver->SetOrigin(offvecx, offvecy);
		_pExtTmpChrUOver->SetOrigin(offvecx+motion_x, offvecy+ motion_y);
		_pExtTmpChrVOver->SetOrigin(offvecx+motion_x, offvecy+ motion_y);
		if( !eighth_motion_x && !eighth_motion_y )	/// No eighth pel implies straight copy.
		{
			_pRefChrUOver->Write(*_pExtTmpChrUOver);
			_pRefChrVOver->Write(*_pExtTmpChrVOver);
		}//end if !eighth_motion_x...
		else
		{
			/// Read the compensated block into a work area and write it to the ref.
			_pExtTmpChrUOver->EighthRead(*_pMBlkOver, eighth_motion_x, eighth_motion_y);
			_pRefChrUOver->Write(*_pMBlkOver);
			_pExtTmpChrVOver->EighthRead(*_pMBlkOver, eighth_motion_x, eighth_motion_y);
			_pRefChrVOver->Write(*_pMBlkOver);
		}//end else...

    /// Reset the invalidation.
    _invalid = 0;
  }//end if mvx...

}//end Compensate.

/*
--------------------------------------------------------------------------------------
	Redundant code.
--------------------------------------------------------------------------------------
*/
/*
void MotionCompensatorH264ImplStd::Compensate(int tlx, int tly, int mvx, int mvy)
{
	int x,y;

	// Extract vector and copy.
	if( mvx || mvy )
  {
    // Lum first.
    int motion_x			= mvx / 2;
    int motion_y			= mvy / 2;
    int half_motion_x	= mvx % 2;
    int half_motion_y	= mvy % 2;

   // Treat the half pel conditions differently.
    if(!half_motion_y && !half_motion_x) // Both zero.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row = tly + y;
        int c_row = tly + y + motion_y;
        if(c_row < 0)
          c_row = 0;
        if(c_row >= _imgHeight)
          c_row = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col = tlx + x;
          int c_col = tlx + x + motion_x;
          if(c_col < 0)
            c_col = 0;
          if(c_col >= _imgWidth)
            c_col = _imgWidth - 1;
          _refLum[r_row][r_col] = _tmpLum[c_row][c_col];
        }//end for x...
      }//end for y...
    }//end if half_motion_y...
    else if(half_motion_y && half_motion_x) // Diagonals.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row = tly + y;
        int c_row1 = tly + y + motion_y;
        int c_row2 = tly + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _imgHeight)
          c_row1 = _imgHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _imgHeight)
          c_row2 = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col	= tlx + x;
          int c_col1 = tlx + x + motion_x;
          int c_col2 = tlx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _imgWidth)
            c_col1 = _imgWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _imgWidth)
            c_col2 = _imgWidth - 1;
          _refLum[r_row][r_col] = (_tmpLum[c_row1][c_col1] + _tmpLum[c_row1][c_col2] +
																 _tmpLum[c_row2][c_col1] + _tmpLum[c_row2][c_col2] + 2)/4;
        }//end for x...
      }//end for y...
    }//end else if half_motion_y...
    else // Linear motion.
    {
      for(y = 0; y < _macroBlkHeight; y++)
      {
        int r_row	= tly + y;
        int c_row1 = tly + y + motion_y;
        int c_row2 = tly + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _imgHeight)
          c_row1 = _imgHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _imgHeight)
          c_row2 = _imgHeight - 1;
        for(x = 0; x < _macroBlkWidth; x++)
        {
          int r_col	= tlx + x;
          int c_col1 = tlx + x + motion_x;
          int c_col2 = tlx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _imgWidth)
            c_col1 = _imgWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _imgWidth)
            c_col2 = _imgWidth - 1;
          _refLum[r_row][r_col] = (_tmpLum[c_row1][c_col1] + _tmpLum[c_row2][c_col2] + 1)/2;
        }//end for x...
      }//end for y...
    }//end else...

    // Chr second.
    int offvecx	= tlx/2;
    int offvecy	= tly/2;
    half_motion_x			= motion_x % 2;
    half_motion_y			= motion_y % 2;
    motion_x					= motion_x / 2;
    motion_y					= motion_y / 2;
    // Treat the half pel conditions differently.
    if(!half_motion_y && !half_motion_x) // Both zero.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row = offvecy + y + motion_y;
        if(c_row < 0)
          c_row = 0;
        if(c_row >= _chrHeight)
          c_row = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col = offvecx + x + motion_x;
          if(c_col < 0)
            c_col = 0;
          if(c_col >= _chrWidth)
            c_col = _chrWidth - 1;
          _refChrU[r_row][r_col] = _tmpChrU[c_row][c_col];
          _refChrV[r_row][r_col] = _tmpChrV[c_row][c_col];
        }//end for x...
      }//end for y...
    }//end if half_motion_y...
    else if(half_motion_y && half_motion_x) // Diagonals.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row1 = offvecy + y + motion_y;
        int c_row2 = offvecy + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _chrHeight)
          c_row1 = _chrHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _chrHeight)
          c_row2 = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col1 = offvecx + x + motion_x;
          int c_col2 = offvecx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _chrWidth)
            c_col1 = _chrWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _chrWidth)
            c_col2 = _chrWidth - 1;
          _refChrU[r_row][r_col] = (_tmpChrU[c_row1][c_col1] + _tmpChrU[c_row1][c_col2] +
																	_tmpChrU[c_row2][c_col1] + _tmpChrU[c_row2][c_col2] + 2)/4;
          _refChrV[r_row][r_col] = (_tmpChrV[c_row1][c_col1] + _tmpChrV[c_row1][c_col2] +
																	_tmpChrV[c_row2][c_col1] + _tmpChrV[c_row2][c_col2] + 2)/4;
        }//end for x...
      }//end for y...
    }//end else if half_motion_y...
    else // Linear motion.
    {
      for(y = 0; y < _chrMacroBlkHeight; y++)
      {
        int r_row = offvecy + y;
        int c_row1 = offvecy + y + motion_y;
        int c_row2 = offvecy + y + motion_y + half_motion_y;
        if(c_row1 < 0)
          c_row1 = 0;
        if(c_row1 >= _chrHeight)
          c_row1 = _chrHeight - 1;
        if(c_row2 < 0)
          c_row2 = 0;
        if(c_row2 >= _chrHeight)
          c_row2 = _chrHeight - 1;
        for(x = 0; x < _chrMacroBlkWidth; x++)
        {
          int r_col = offvecx + x;
          int c_col1 = offvecx + x + motion_x;
          int c_col2 = offvecx + x + motion_x + half_motion_x;
          if(c_col1 < 0)
            c_col1 = 0;
          if(c_col1 >= _chrWidth)
            c_col1 = _chrWidth - 1;
          if(c_col2 < 0)
            c_col2 = 0;
          if(c_col2 >= _chrWidth)
            c_col2 = _chrWidth - 1;
          _refChrU[r_row][r_col] = (_tmpChrU[c_row1][c_col1] + _tmpChrU[c_row2][c_col2] + 1)/2;
          _refChrV[r_row][r_col] = (_tmpChrV[c_row1][c_col1] + _tmpChrV[c_row2][c_col2] + 1)/2;
        }//end for x...
      }//end for y...
    }//end else...
  }//end if mvx...

}//end Compensate.
*/
========== END FILE: CodecUtils/MotionCompensatorH264ImplStd.cpp ==========

========== BEGIN FILE: CodecUtils/MotionCompensatorH264ImplStd.h ==========
Bundle entry: 82
Original bytes: 6391
Original SHA-256: 7a758186ae1b894e381cf336453031027bd7037e091e8102ff1a79bffca9585c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionCompensatorH264ImplStd

TAG						: MCH264IS

FILE NAME			: MotionCompensatorH264ImplStd.h

DESCRIPTION		: A fast unrestricted motion compensator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionCompensator interface. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONCOMPENSATORH264IMPLSTD_H
#define _MOTIONCOMPENSATORH264IMPLSTD_H

#include "IMotionCompensator.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionCompensatorH264ImplStd : public IMotionCompensator
{
	// Construction.
	public:

		MotionCompensatorH264ImplStd(int range);
		virtual ~MotionCompensatorH264ImplStd(void);

	// IMotionCompensator Interface.
	public:
		
		virtual int	Create(	void* ref, 
												int imgWidth,	int imgHeight, 
												int macroBlkWidth, int macroBlkHeight);
		virtual void	Destroy(void);
		virtual void	Reset(void);

		/** Motion compensate to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create().
		@param pMotionList	: The list of motion vectors.
		@return							: None.
		*/
		virtual void Compensate(void* pMotionList);

		/** Motion compensate a single vector to the reference.
		Do the compensation with the block sizes and image sizes defined in
		the implementation and set in Create(). The vector coords are in 
		quarter pel units for this implementation. NOTE: The temp image must
		hold a copy of the ref BEFORE using this method and is should be done
		in PrepareForSingleVectorMode().
		@param tlx	: Top left x coord of block.
		@param tly	: Top left y coord of block.
		@param mvx	: X coord of the motion vector.
		@param mvy	: Y coord of the motion vector.
		@return			: None.
		*/
		virtual void Compensate(int tlx, int tly, int mvx, int mvy);

		/** Prepare the ref for single motion vector compensation mode.
		Should be used to copy the ref into a temp location from which to
		do the compensation to the ref. Prevents interference and double
		compensation. Use the Invalidate() command to force compensation
    on a vector by vector basis.
		@return : none.
		*/
		virtual void PrepareForSingleVectorMode(void);
    virtual void Invalidate(void) { _invalid = 1; }

	/// Local methods.
	protected:
	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

	/// Local methods.
	protected:

		/// Parameters must remain const for the life time of this instantiation.
		int	_imgWidth;				///< Width of the ref images. 
		int	_imgHeight;				///< Height of the ref images.
		int _chrWidth;
		int _chrHeight;
		int	_macroBlkWidth;		///< Width of the motion block.
		int	_macroBlkHeight;	///< Height of the motion block.
		int _chrMacroBlkWidth;
		int _chrMacroBlkHeight;
		int _range;						///< Max range of the motion [-_range ... (_range-1)] in full pel units.
    int _invalid;         ///< Invalidate the compensation to force copying on the next compensated vector. Cleared after use.

		int _refSize;					///< Total size of the contiguous Lum, ChrU, ChrV.
		/// Ref image holders.
		short*		_pRefLum;		///< References to the images at creation.
		short*		_pRefChrU;
		short*		_pRefChrV;

		/// Overlays to the ref image.
		OverlayMem2Dv2*	_pRefLumOver;
		OverlayMem2Dv2*	_pRefChrUOver;
		OverlayMem2Dv2*	_pRefChrVOver;

		/// Extended temp ref mem created by ExtendBoundary() calls for each colour
		/// component and an extended boundary overlay for each.
		short*							_pExtTmpLum;
		OverlayExtMem2Dv2*	_pExtTmpLumOver;
		int									_extLumWidth;
		int									_extLumHeight;
		short*							_pExtTmpChrU;
		OverlayExtMem2Dv2*	_pExtTmpChrUOver;
		short*							_pExtTmpChrV;
		OverlayExtMem2Dv2*	_pExtTmpChrVOver;
		int									_extChrWidth;
		int									_extChrHeight;

		/// A work block.
		short*					_pMBlk;
		OverlayMem2Dv2* _pMBlkOver;
};//end MotionCompensatorH264ImplStd.


#endif	// _MOTIONCOMPENSATORH264IMPLSTD_H
========== END FILE: CodecUtils/MotionCompensatorH264ImplStd.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH263ImplMultiresCross.cpp ==========
Bundle entry: 83
Original bytes: 43743
Original SHA-256: f405eddc3718822748d20fbf8570f1a15c4f00245cd10ce58b511bf72822db57
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH263ImplMultiresCross

TAG						: MEH263IMC

FILE NAME			: MotionEstimatorH263ImplMultiresCross.cpp

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.263 (02/98) Annex D page 53 of absolute 
								error difference measure.	Access via a IMotionEstimator	
								interface. There are 2 mode levels of execution speed vs. 
								quality. At the lowest resolution a converging cross search
								method is used to find the best block match. The boundary 
								is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include	"MotionEstimatorH263ImplMultiresCross.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH263IMC_FULL_MOTION_NOISE_FLOOR						512
#define MEH263IMC_MOTION_NOISE_FLOOR								26 //24 //sqrt 512
#define MEH263IMC_L0_MOTION_VECTOR_REFINED_RANGE		2
#define MEH263IMC_L1_MOTION_VECTOR_REFINED_RANGE		2

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Different for different levels.
#define MEH263IMC_PADDING													1	
#define MEH263IMC_L1_PADDING											1	
#define MEH263IMC_L2_PADDING											1	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH263IMC_ABS_DIFF

#define MEH263IMC_MOTION_HALF_POS_LENGTH 	8
MEH263IMC_COORD MEH263IMC_HalfPos[MEH263IMC_MOTION_HALF_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH263IMC_MOTION_CROSS_POS_LENGTH 	4
MEH263IMC_COORD MEH263IMC_CrossPos[MEH263IMC_MOTION_CROSS_POS_LENGTH]	= 
{
	{-1,0},{1,0},{0,-1},{0,1}
};

/// The half pel motion search is split into two steps. Firstly, find the best corner
/// position and then, secondly, refine this with each cross located pel around the
/// winner. Note that a full cross will be required if the (0,0) vector remains the
/// best.
#define MEH263IMC_MOTION_HALF_CORNER_POS_LENGTH 	4
MEH263IMC_COORD MEH263IMC_HalfCornerPos[MEH263IMC_MOTION_HALF_CORNER_POS_LENGTH]	= 
{
	{-1,-1},{1,-1},{-1,1},{1,1}
};
#define MEH263IMC_MOTION_HALF_REFINED_POS_LENGTH 	2
MEH263IMC_COORD MEH263IMC_HalfRefinedPos[4][MEH263IMC_MOTION_HALF_REFINED_POS_LENGTH]	= 
{
	{ { 0,-1}, {-1, 0} }, ///< For {-1,-1} winner.
	{ { 0,-1}, { 1, 0} }, ///< For { 1,-1}
	{ { 0, 1}, {-1, 0} }, ///< For {-1, 1}
	{ { 0, 1}, { 1, 0} }  ///< For { 1, 1}
};


/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH263ImplMultiresCross::MotionEstimatorH263ImplMultiresCross(	const void* pSrc, 
																														const void* pRef, 
																														int					imgWidth, 
																														int					imgHeight,
																														int					motionRange)
{
	ResetMembers();
	
	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (2x,2y) range of the motion vectors.
	_pInput					= pSrc;
	_pRef						= pRef;

}//end constructor.

MotionEstimatorH263ImplMultiresCross::MotionEstimatorH263ImplMultiresCross(	const void* pSrc, 
																														const void* pRef, 
																														int					imgWidth, 
																														int					imgHeight,
																														int					motionRange,
																														void*				pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (2x,2y) range of the motion vectors.
	_pInput								= pSrc;
	_pRef									= pRef;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH263ImplMultiresCross::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.263.
	_motionRange		= 32;					///< (2x,2y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Level 0: Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2.
	_pInL1						= NULL;			///< Input mem at (_l1Width * _l1Height).
	_l1Width					= 0;
	_l1Height					= 0;
	_l1MacroBlkWidth	= 0;
	_l1MacroBlkHeight = 0;
	_l1MotionRange		= 0;
	_pInL1Over				= NULL;			///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.
	_pInL2						= NULL;			///< Input mem at (_l2Width * _l2Height).
	_l2Width					= 0;
	_l2Height					= 0;
	_l2MacroBlkWidth	= 0;
	_l2MacroBlkHeight = 0;
	_l2MotionRange		= 0;
	_pInL2Over				= NULL;			///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.
	_pRefL1						= NULL;			///< Ref mem at (_l1Width * _l1Height).
	_pRefL1Over				= NULL; 		///< Ref overlay with whole level 1 block dim.
	_pExtRefL1				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL1Width				= 0;
	_extL1Height			= 0;
	_extL1Boundary		= 0;
	_pExtRefL1Over		= NULL;			///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.
	_pRefL2						= NULL;			///< Ref mem at (_l2Width * _l2Height).
	_pRefL2Over				= NULL; 		///< Ref overlay with whole level 2 block dim.
	_pExtRefL2				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL2Width				= 0;
	_extL2Height			= 0;
	_extL2Boundary		= 0;
	_pExtRefL2Over		= NULL;			///< Ref overlay with level 2 motion block dim.

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH263ImplMultiresCross::~MotionEstimatorH263ImplMultiresCross(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH263ImplMultiresCross::Create(void)
{
	// Clean out old mem.
	Destroy();

	// --------------- Configure input overlays --------------------------------
	// Level 0: Put an overlay on the input with the block size set to the vector 
	// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((void *)_pInput, 
															_imgWidth, 
															_imgHeight, 
															_macroBlkWidth, 
															_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// Level 1 is Level 0 sub sampled by 2.
	_l1Width					= _imgWidth/2;
	_l1Height					= _imgHeight/2;
	_l1MacroBlkWidth	= _macroBlkWidth/2;
	_l1MacroBlkHeight = _macroBlkHeight/2;
	_l1MotionRange		= _motionRange/4;	///< _motionRange is in half pel units.

	// Level 1: Input mem at (_l1Width * _l1Height) must be alloc.
	_pInL1 = new short[_l1Width * _l1Height];

	// Level 1: Input overlay with level 1 motion block dim.
	if(_pInL1 != NULL)
	{
		_pInL1Over = new OverlayMem2Dv2(_pInL1, 
																	_l1Width, 
																	_l1Height, 
																	_l1MacroBlkWidth, 
																	_l1MacroBlkHeight);
		if(_pInL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL1Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2 is Level 1 sub sampled by 2.
	_l2Width					= _l1Width/2;
	_l2Height					= _l1Height/2;
	_l2MacroBlkWidth	= _l1MacroBlkWidth/2;
	_l2MacroBlkHeight = _l1MacroBlkHeight/2;
	_l2MotionRange		= _l1MotionRange/2;

	// Level 2: Input mem at (_l2Width * _l2Height) must be alloc.
	_pInL2 = new short[_l2Width * _l2Height];

	// Level 2: Input overlay with level 2 motion block dim.
	if(_pInL2 != NULL)
	{
		_pInL2Over = new OverlayMem2Dv2(_pInL2, 
																	_l2Width, 
																	_l2Height, 
																	_l2MacroBlkWidth, 
																	_l2MacroBlkHeight);
		if(_pInL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL2Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// --------------- Configure ref overlays --------------------------------
	/// Level 0: Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore have its own mem.
	_pRefOver = new OverlayMem2Dv2((void *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	// the max dimension of the macroblock.
	_extBoundary = _macroBlkWidth + MEH263IMC_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH263IMC_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																			_imgWidth,						
																			_imgHeight, 
																			_extBoundary,	// Extend left and right by...
																			_extBoundary,	// Extend top and bottom by...
																			(void **)(&_pExtRef)) )	// Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Level 0: Place an overlay on the extended boundary ref with block 
	/// size set to the motion vec dim..
	_pExtRefOver = new OverlayExtMem2Dv2(_pExtRef,				// Src description. 
																		 _extWidth, 
																		 _extHeight,
																		 _macroBlkWidth,	// Block size description.
																		 _macroBlkHeight,
																		 _extBoundary,		// Boundary size for both left and right.
																		 _extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// Level 1: Ref mem at (_l1Width * _l1Height).
	_pRefL1 = new short[_l1Width * _l1Height];

	/// Level 1: Ref overlay with whole level 1 block dim.
	if(_pRefL1 != NULL)
	{
		_pRefL1Over = new OverlayMem2Dv2(_pRefL1, _l1Width, _l1Height, _l1Width, _l1Height);
		if(_pRefL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL1Over...
	}//end if _pRefL1...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 1: Extended ref mem _pExtRefL1 created by ExtendBoundary() call.
	_extL1Boundary = _l1MacroBlkWidth + MEH263IMC_L1_PADDING;
	if(_l1MacroBlkHeight > _l1MacroBlkWidth)
		_extL1Boundary = _l1MacroBlkHeight + MEH263IMC_L1_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL1, 
																			_l1Width,						
																			_l1Height, 
																			_extL1Boundary,
																			_extL1Boundary,
																			(void **)(&_pExtRefL1)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL1Width		= _l1Width + (2 * _extL1Boundary);
	_extL1Height	= _l1Height + (2 * _extL1Boundary);

	// Level 1: Ref overlay with level 1 motion block dim.
	_pExtRefL1Over = new OverlayExtMem2Dv2(_pExtRefL1, 
																			 _extL1Width,					// new mem width.
																			 _extL1Height,				// new mem height.
																			 _l1MacroBlkWidth,		// block width.
																			 _l1MacroBlkHeight,		// block height.
																			 _extL1Boundary,			// boundary width.
																			 _extL1Boundary);			// boundary height.
	if(_pExtRefL1Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL1Over...

	/// Level 2: Ref mem at (_l2Width * _l2Height).
	_pRefL2 = new short[_l2Width * _l2Height];

	/// Level 2: Ref overlay with whole level 2 block dim.
	if(_pRefL2 != NULL)
	{
		_pRefL2Over = new OverlayMem2Dv2(_pRefL2, _l2Width, _l2Height, _l2Width, _l2Height);
		if(_pRefL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL2Over...
	}//end if _pRefL2...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2: Extended ref mem _pExtRefL2 created by ExtendBoundary() call.
	_extL2Boundary = _l2MacroBlkWidth + MEH263IMC_L2_PADDING;
	if(_l2MacroBlkHeight > _l2MacroBlkWidth)
		_extL2Boundary = _l2MacroBlkHeight + MEH263IMC_L2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL2, 
																			_l2Width,						
																			_l2Height, 
																			_extL2Boundary,
																			_extL2Boundary,
																			(void **)(&_pExtRefL2)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL2Width		= _l2Width + (2 * _extL2Boundary);
	_extL2Height	= _l2Height + (2 * _extL2Boundary);

	/// Level 2: Ref overlay with level 2 motion block dim.
	_pExtRefL2Over = new OverlayExtMem2Dv2(_pExtRefL2, 
																			 _extL2Width,					// new mem width.
																			 _extL2Height,				// new mem height.
																			 _l2MacroBlkWidth,		// block width.
																			 _l2MacroBlkHeight,		// block height.
																			 _extL2Boundary,			// boundary width.
																			 _extL2Boundary);			// boundary height.
	if(_pExtRefL2Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL2Over...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half pel motion estimation and 
	/// compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																				_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	_ready = 1;
	return(1);
}//end Create.

void	MotionEstimatorH263ImplMultiresCross::Reset(void)
{
}//end Reset.

/** Set the speed mode.
This is a multresolution algorithm and the speed is increased by estimating
at lower levels but it is less accurate. Mode = 1 implies level 1 and mode = 2
for level 2. Mode = 0 is auto mode that selects an appropriate mode depending
on the resolution of the image. The selection is set to 2 if the image has
an area larger than 200x200.

@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void	MotionEstimatorH263ImplMultiresCross::SetMode(int mode)
 {
	if(mode == 0)	// Auto mode.
	{
		int area = _imgWidth * _imgHeight;
		if(area > 40000)
			_mode = 2;
		else
			_mode = 1;
	}//end if mode...
	else
		_mode = mode;
}//end SetMode.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries and a
absolute difference criterion. The mode setting (_mode) determines
the level of resolution.
@param pSrc		: Input image to estimate.
@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void* MotionEstimatorH263ImplMultiresCross::Estimate(long* avgDistortion)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH263IMC_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver is always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),			///< Src 2D ptr.
										  _imgWidth, 																///< Src width.
											_imgHeight, 															///< Src height.
											(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
												_l1Width, 																///< Src width.
												_l1Height, 																///< Src height.
												(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gathers the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< Half pel grid.
		int hmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The [0,0] vector	difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting point.

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute/square diff comparison method.
#ifdef MEH263IMC_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far.

		///----------------------- Level 2 cross pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Absolute diff comparison method.
#ifdef MEH263IMC_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif
			
    	/// Level 2: Search on a full pel grid over the defined L2 motion range.
			
			/// Cross search loop.
			for(int w = _l2MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH263IMC_MOTION_CROSS_POS_LENGTH; x++)
				{
                                        int blkDiff = 0;
					i = w * MEH263IMC_CrossPos[x].y;
					j = w * MEH263IMC_CrossPos[x].x;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH263IMC_LEVEL2_BREAK;

					/// Set the block to the (j,i) offset motion vector from the (mx,my) motion vector
					/// around the (l,k) reference location.
					_pExtRefL2Over->SetOrigin(j+l+mx, i+k+my);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4LessThan(*_pExtRefL2Over, minDiffL2);
#else
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif

					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL2)
						{
							int vecDistDiff = ( (my*my)+(mx*mx) )-( (i*i)+(j*j) );
							if(vecDistDiff < 0)
								goto MEH263IMC_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...
			
					MEH263IMC_LEVEL2_BREAK: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

			mx = mx << 1; /// Convert level 2 to level 1 grid units ( x2 ).
			my = my << 1;
			
		}//end if _mode...

		///----------------------- Level 1 full/cross pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);
		/// Absolute diff comparison method.
#ifdef MEH263IMC_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Level 1: Search on a cross pel grid over the defined L1 motion range if mode != 2. The
		///					 range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;

		/// For mode = 2 (level 2 search has been done) do a refinement search.
		if(_mode == 2)
		{
			GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

			for(i = yuRng; i <= ydRng; i++)
			{
				for(j = xlRng; j <= xrRng; j++)
				{
                                        int blkDiff = 0;
					/// Early exit because zero (centre) motion vec already checked.
					if( !(i||j) )	goto MEH263IMC_LEVEL1_BREAK;

					/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMC_ABS_DIFF
				        blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH263IMC_LEVEL1_BREAK;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH263IMC_LEVEL1_BREAK: ; ///< null.
				}//end for j...
			}//end for i...
		}//end if mode == 2...
		else	///< Do a cross search.
		{
			/// For this case, this is the first entry point of the search i.e. (mx,my) = (0,0).

			for(int w = _l1MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange-1, 1);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH263IMC_MOTION_CROSS_POS_LENGTH; x++)
				{
                                        int blkDiff = 0; 
					i = w * MEH263IMC_CrossPos[x].y;
					j = w * MEH263IMC_CrossPos[x].x;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH263IMC_LEVEL1_BREAK_C;

					/// Set the block to the (j,i) motion vector around the (mx+p,my+q) reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif

					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH263IMC_LEVEL1_BREAK_C;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH263IMC_LEVEL1_BREAK_C: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...
		}//end else...

		mx = (mx+rmx) * 2; ///< Convert level 1 to level 0 grid units ( x2 ) and add the refinement.
		my = (my+rmy) * 2;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range.

		/// Get the min diff at this location in level 0 grid units.
		_pExtRefOver->SetOrigin(n+mx,m+my);

#ifdef MEH263IMC_ABS_DIFF
		minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH263IMC_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
      for(j = xlRng; j <= xrRng; j++)
      {
                                int blkDiff = 0;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH263IMC_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH263IMC_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
//				int blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global motion vector magnitude. 
					if(blkDiff == minDiff)
					{
						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
						if(vecDistDiff < 0)
							goto MEH263IMC_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH263IMC_LEVEL0_BREAK: ; ///< null.
      }//end for j...
    }//end for i...

		/// Add the refinement.
		mx += rmx;
		my += rmy;

		///----------------------- Level 0 half pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a half pel grid.

		/// Set the location to the current min diff motion vector [mx,my].
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// The half pel motion search is split into two steps. Firstly, find the best corner
		/// position and then, secondly, refine this with each cross located pel around the
		/// winner. Note that a full cross will be required if the (0,0) vector remains the
		/// best.
		/// ---------- Step 1 -------------------------
		int bestCorner = 0;
    for(int corner = 0; corner < MEH263IMC_MOTION_HALF_CORNER_POS_LENGTH; corner++)
    {
			int hOffX = MEH263IMC_HalfCornerPos[corner].x;
			int hOffY = MEH263IMC_HalfCornerPos[corner].y;

			/// Read the half grid pels into temp.
			_pExtRefOver->HalfRead(*_pMBlkOver, hOffX, hOffY);

#ifdef MEH263IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				bestCorner	= corner;
				minDiff			= blkDiff;
				hmx					= hOffX;
				hmy					= hOffY;
			}//end if blkDiff...
    }//end for corner...

		/// ---------- Step 2 -------------------------
		MEH263IMC_COORD*	pattern			= MEH263IMC_HalfRefinedPos[bestCorner];
		int								patternLen	= MEH263IMC_MOTION_HALF_REFINED_POS_LENGTH;
		/// If no corner was better than the (0,0) half pos then do a full cross.
		if( !hmx && !hmy )
		{
			pattern			= MEH263IMC_CrossPos;
			patternLen	= MEH263IMC_MOTION_CROSS_POS_LENGTH;
		}//end if !hmx...
    for(int cross = 0; cross < patternLen; cross++)
    {
			int hOffX = pattern[cross].x;
			int hOffY = pattern[cross].y;

			/// Read the half grid pels into temp.
			_pExtRefOver->HalfRead(*_pMBlkOver, hOffX, hOffY);

#ifdef MEH263IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = hOffX;
				hmy = hOffY;
			}//end if blkDiff...
    }//end for cross...

		/// Add the refinement in half pel units.
		int mvx = (mx << 1) + hmx;
		int mvy = (my << 1) + hmy;

		/// Bounds check used for debugging only as minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx > (_motionRange-1))
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy > (_motionRange-1))
		//	mvy = (_motionRange-1);

		/// Validity of the motion vector is weighted with non-linear factors.
		int weight							= 0;
		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int magSqr							= (mvx * mvx) + (mvy * mvy);

#ifdef MEH263IMC_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff >> 1) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH263IMC_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff >> 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH263IMC_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Determine the basic run-length motion.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = 0;
			mvy = 0;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH263ImplMultiresCross::Destroy(void)
{
	_ready = 0;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pInL1 != NULL)
		delete[] _pInL1;
	_pInL1 = NULL;

	if(_pInL1Over != NULL)
		delete _pInL1Over;
	_pInL1Over = NULL;

	if(_pInL2 != NULL)
		delete[] _pInL2;
	_pInL2 = NULL;

	if(_pInL2Over != NULL)
		delete _pInL2Over;
	_pInL2Over = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pRefL1 != NULL)
		delete[] _pRefL1;
	_pRefL1	= NULL;

	if(_pRefL1Over != NULL)
		delete _pRefL1Over;
	_pRefL1Over	= NULL;

	if(_pExtRefL1 != NULL)
		delete[] _pExtRefL1;
	_pExtRefL1 = NULL;

	if(_pExtRefL1Over != NULL)
		delete _pExtRefL1Over;
	_pExtRefL1Over = NULL;

	if(_pRefL2 != NULL)
		delete[] _pRefL2;
	_pRefL2	= NULL;

	if(_pRefL2Over != NULL)
		delete _pRefL2Over;
	_pRefL2Over	= NULL;

	if(_pExtRefL2 != NULL)
		delete[] _pExtRefL2;
	_pExtRefL2 = NULL;

	if(_pExtRefL2Over != NULL)
		delete _pExtRefL2Over;
	_pExtRefL2Over = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.263 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed x left range.
@param xrr			: Returned allowed x right range.
@param yur			: Returned allowed y up range.
@param ydr			: Returned allowed y down range.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH263ImplMultiresCross::GetMotionRange(int  x,			int  y, 
																									int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range,	int	 level)
{
	// The level defines the members to use.
	int boundary, width, height;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary;
			width			= _l1Width;
			height		= _l1Height;
			break;
		case 2 :
			boundary	= _extL2Boundary;
			width			= _l2Width;
			height		= _l2Height;
			break;
		case 0 :
		default :
			boundary	= _extBoundary;
			width			= _imgWidth;
			height		= _imgHeight;
			break;
	}//end switch level...

	if( (x - range) >= -boundary )	// Ok and within left extended boundary.
		*xlr = -range;
	else // Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	// Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	// Ok and within upper extended boundary.
		*yur = -range;
	else // Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	// Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH263ImplMultiresCross::GetMotionRange(	int  xpos,	int  ypos,
																														int	 xoff,	int  yoff,
																														int* xlr,		int* xrr, 
																														int* yur,		int* ydr,
																														int	 range,	int	 level)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	/// The level defines the members to use.
	int boundary, width, height, vecRange;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH263IMC_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			vecRange	= _l1MotionRange;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH263IMC_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			vecRange	= _l2MotionRange;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH263IMC_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			vecRange	= _motionRange/2;	///< Convert 1/2 pel range to full pel units.
			break;
	}//end switch level...

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.




========== END FILE: CodecUtils/MotionEstimatorH263ImplMultiresCross.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH263ImplMultiresCross.h ==========
Bundle entry: 84
Original bytes: 8455
Original SHA-256: ec122acb5f4a27bdeb277f23e2851dfd4a766adf06d1a57d019abcf7c19b609c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH263ImplMultiresCross

TAG						: MEH263IMC

FILE NAME			: MotionEstimatorH263ImplMultiresCross.h

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.263 (02/98) Annex D page 53 of absolute 
								error difference measure.	Access via a IMotionEstimator	
								interface. There are 2 mode levels of execution speed vs. 
								quality. At the lowest resolution a converging cross search
								method is used to find the best block match. The boundary 
								is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH263IMPLMULTIRESCROSS_H
#define _MOTIONESTIMATORH263IMPLMULTIRESCROSS_H

#include "IMotionEstimator.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH263IMC_COORD
{
	short int x;
	short int y;
} MEH263IMC_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH263ImplMultiresCross : public IMotionEstimator
{
// Construction.
public:

	MotionEstimatorH263ImplMultiresCross(	const void* pSrc, 
																				const void* pRef, 
																				int					imgWidth, 
																				int					imgHeight,
																				int					motionRange);

	MotionEstimatorH263ImplMultiresCross(	const void* pSrc, 
																				const void* pRef, 
																				int					imgWidth, 
																				int					imgHeight,
																				int					motionRange,
																				void*				pDistortionIncluded);

	virtual ~MotionEstimatorH263ImplMultiresCross(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
	virtual void	Reset(void);
	virtual int		Ready(void)		{ return(_ready); }
	virtual void	SetMode(int mode);
	virtual int		GetMode(void) { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 

protected:

	int _ready;	// Ready to estimate.
	int _mode;	// Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				// Width of the src and ref images. 
	int	_imgHeight;				// Height of the src and ref images.
	int	_macroBlkWidth;		// Width of the motion block.
	int	_macroBlkHeight;	// Height of the motion block.
	int	_motionRange;			// (x,y) range of the motion vectors.

	const void*	_pInput;	// References to the images at construction.
	const void* _pRef;

	// Level 0: Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					// Input overlay with motion block dim.
	// Level 1: Subsampled input by 2. [_mode == 1]
	short*						_pInL1;						// Input mem at (_l1Width * _l1Height).
	int								_l1Width;
	int								_l1Height;
	int								_l1MacroBlkWidth;
	int								_l1MacroBlkHeight;
	int								_l1MotionRange;
	OverlayMem2Dv2*		_pInL1Over;				// Input overlay with level 1 motion block dim.
	// Level 2: Subsampled input by 4.	[_mode == 2]
	short*						_pInL2;						// Input mem at (_l2Width * _l2Height).
	int								_l2Width;
	int								_l2Height;
	int								_l2MacroBlkWidth;
	int								_l2MacroBlkHeight;
	int								_l2MotionRange;
	OverlayMem2Dv2*		_pInL2Over;				// Input overlay with level 2 motion block dim.

	// Level 0: Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				// Ref overlay with whole block dim.
	short*							_pExtRef;					// Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			// Extended ref overlay with motion block dim.
	// Level 1: Subsampled ref by 2.		[_mode == 1]
	short*							_pRefL1;					// Ref mem at (_l1Width * _l1Height).
	OverlayMem2Dv2*			_pRefL1Over; 			// Ref overlay with whole level 1 block dim.
	short*							_pExtRefL1;				// Extended ref mem create by ExtendBoundary() call.
	int									_extL1Width;
	int									_extL1Height;
	int									_extL1Boundary;		// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL1Over;		// Ref overlay with level 1 motion block dim.
	// Level 2: Subsampled ref by 4.		[_mode == 2]
	short*							_pRefL2;					// Ref mem at (_l2Width * _l2Height).
	OverlayMem2Dv2*			_pRefL2Over; 			// Ref overlay with whole level 2 block dim.
	short*							_pExtRefL2;				// Extended ref mem create by ExtendBoundary() call.
	int									_extL2Width;
	int									_extL2Height;
	int									_extL2Boundary;		// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL2Over;		// Ref overlay with level 2 motion block dim.

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH263ImplMultiresCross.


#endif // !_MOTIONESTIMATORH263IMPLMULTIRESCROSS_H

========== END FILE: CodecUtils/MotionEstimatorH263ImplMultiresCross.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.cpp ==========
Bundle entry: 85
Original bytes: 49085
Original SHA-256: 148dc37ea2650bb3b863b9739dacdf1a3e927cb249efc726f1e6c917c74ddc41
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH263ImplMultiresCrossVer2

TAG						: MEH263IMCV2

FILE NAME			: MotionEstimatorH263ImplMultiresCrossVer2.cpp

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.263 (02/98) Annex D page 53 of absolute 
								error difference measure.	Access via a IMotionEstimator	
								interface. There are 2 mode levels of execution speed vs. 
								quality. At the lowest resolution a converging cross search
								method is used to find the best block match. The boundary 
								is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include	"MotionEstimatorH263ImplMultiresCrossVer2.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH263IMCV2_FULL_MOTION_NOISE_FLOOR						512
#define MEH263IMCV2_MOTION_NOISE_FLOOR								26 //24 //sqrt 512
#define MEH263IMCV2_L0_MOTION_VECTOR_REFINED_RANGE		2
#define MEH263IMCV2_L1_MOTION_VECTOR_REFINED_RANGE		2

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Different for different levels.
#define MEH263IMCV2_PADDING													1	
#define MEH263IMCV2_L1_PADDING											1	
#define MEH263IMCV2_L2_PADDING											1

/// Choose between sqr err distortion or abs diff metric.
#undef MEH263IMCV2_ABS_DIFF

#define MEH263IMCV2_MOTION_HALF_POS_LENGTH 	8
MEH263IMCV2_COORD MEH263IMCV2_HalfPos[MEH263IMCV2_MOTION_HALF_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH263IMCV2_MOTION_CROSS_POS_LENGTH 	4
MEH263IMCV2_COORD MEH263IMCV2_CrossPos[MEH263IMCV2_MOTION_CROSS_POS_LENGTH]	= 
{
	{-1,0},{1,0},{0,-1},{0,1}
};

/// The half pel motion search is split into two steps. Firstly, find the best corner
/// position and then, secondly, refine this with each cross located pel around the
/// winner. Note that a full cross will be required if the (0,0) vector remains the
/// best.
#define MEH263IMCV2_MOTION_HALF_CORNER_POS_LENGTH 	4
MEH263IMCV2_COORD MEH263IMCV2_HalfCornerPos[MEH263IMCV2_MOTION_HALF_CORNER_POS_LENGTH]	= 
{
	{-1,-1},{1,-1},{-1,1},{1,1}
};
#define MEH263IMCV2_MOTION_HALF_REFINED_POS_LENGTH 	2
MEH263IMCV2_COORD MEH263IMCV2_HalfRefinedPos[4][MEH263IMCV2_MOTION_HALF_REFINED_POS_LENGTH]	= 
{
	{ { 0,-1}, {-1, 0} }, ///< For {-1,-1} winner.
	{ { 0,-1}, { 1, 0} }, ///< For { 1,-1}
	{ { 0, 1}, {-1, 0} }, ///< For {-1, 1}
	{ { 0, 1}, { 1, 0} }  ///< For { 1, 1}
};


/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH263ImplMultiresCrossVer2::MotionEstimatorH263ImplMultiresCrossVer2(	const void*             pSrc, 
																														                        const void*             pRef, 
																														                        int					            imgWidth, 
																														                        int					            imgHeight,
																														                        int					            motionRange,
                                                                                    IMotionVectorPredictor* pMVPred)
{
	ResetMembers();
	
	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (2x,2y) range of the motion vectors.
	_pInput					= pSrc;
	_pRef						= pRef;
  _pMVPred        = pMVPred;

}//end constructor.

MotionEstimatorH263ImplMultiresCrossVer2::MotionEstimatorH263ImplMultiresCrossVer2(	const void*             pSrc, 
																														                        const void*             pRef, 
																														                        int					            imgWidth, 
																														                        int					            imgHeight,
																														                        int					            motionRange,
                                                                                    IMotionVectorPredictor* pMVPred,
																														                        void*				            pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (2x,2y) range of the motion vectors.
	_pInput								= pSrc;
	_pRef									= pRef;
  _pMVPred              = pMVPred;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH263ImplMultiresCrossVer2::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.263.
	_motionRange		= 32;					///< (2x,2y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Level 0: Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2.
	_pInL1						= NULL;			///< Input mem at (_l1Width * _l1Height).
	_l1Width					= 0;
	_l1Height					= 0;
	_l1MacroBlkWidth	= 0;
	_l1MacroBlkHeight = 0;
	_l1MotionRange		= 0;
	_pInL1Over				= NULL;			///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.
	_pInL2						= NULL;			///< Input mem at (_l2Width * _l2Height).
	_l2Width					= 0;
	_l2Height					= 0;
	_l2MacroBlkWidth	= 0;
	_l2MacroBlkHeight = 0;
	_l2MotionRange		= 0;
	_pInL2Over				= NULL;			///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.
	_pRefL1						= NULL;			///< Ref mem at (_l1Width * _l1Height).
	_pRefL1Over				= NULL; 		///< Ref overlay with whole level 1 block dim.
	_pExtRefL1				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL1Width				= 0;
	_extL1Height			= 0;
	_extL1Boundary		= 0;
	_pExtRefL1Over		= NULL;			///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.
	_pRefL2						= NULL;			///< Ref mem at (_l2Width * _l2Height).
	_pRefL2Over				= NULL; 		///< Ref overlay with whole level 2 block dim.
	_pExtRefL2				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL2Width				= 0;
	_extL2Height			= 0;
	_extL2Boundary		= 0;
	_pExtRefL2Over		= NULL;			///< Ref overlay with level 2 motion block dim.

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct  = NULL;
  /// Attached motion vector predictor on construction.
  _pMVPred              = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH263ImplMultiresCrossVer2::~MotionEstimatorH263ImplMultiresCrossVer2(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH263ImplMultiresCrossVer2::Create(void)
{
	// Clean out old mem.
	Destroy();

	// --------------- Configure input overlays --------------------------------
	// Level 0: Put an overlay on the input with the block size set to the vector 
	// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((void *)_pInput, 
															_imgWidth, 
															_imgHeight, 
															_macroBlkWidth, 
															_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// Level 1 is Level 0 sub sampled by 2.
	_l1Width					= _imgWidth/2;
	_l1Height					= _imgHeight/2;
	_l1MacroBlkWidth	= _macroBlkWidth/2;
	_l1MacroBlkHeight = _macroBlkHeight/2;
	_l1MotionRange		= _motionRange/4;	///< _motionRange is in half pel units.

	// Level 1: Input mem at (_l1Width * _l1Height) must be alloc.
	_pInL1 = new short[_l1Width * _l1Height];

	// Level 1: Input overlay with level 1 motion block dim.
	if(_pInL1 != NULL)
	{
		_pInL1Over = new OverlayMem2Dv2(_pInL1, 
																	_l1Width, 
																	_l1Height, 
																	_l1MacroBlkWidth, 
																	_l1MacroBlkHeight);
		if(_pInL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL1Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2 is Level 1 sub sampled by 2.
	_l2Width					= _l1Width/2;
	_l2Height					= _l1Height/2;
	_l2MacroBlkWidth	= _l1MacroBlkWidth/2;
	_l2MacroBlkHeight = _l1MacroBlkHeight/2;
	_l2MotionRange		= _l1MotionRange/2;

	// Level 2: Input mem at (_l2Width * _l2Height) must be alloc.
	_pInL2 = new short[_l2Width * _l2Height];

	// Level 2: Input overlay with level 2 motion block dim.
	if(_pInL2 != NULL)
	{
		_pInL2Over = new OverlayMem2Dv2(_pInL2, 
																	_l2Width, 
																	_l2Height, 
																	_l2MacroBlkWidth, 
																	_l2MacroBlkHeight);
		if(_pInL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL2Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// --------------- Configure ref overlays --------------------------------
	/// Level 0: Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore have its own mem.
	_pRefOver = new OverlayMem2Dv2((void *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	// the max dimension of the macroblock.
	_extBoundary = _macroBlkWidth + MEH263IMCV2_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH263IMCV2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																			_imgWidth,						
																			_imgHeight, 
																			_extBoundary,	// Extend left and right by...
																			_extBoundary,	// Extend top and bottom by...
																			(void **)(&_pExtRef)) )	// Created in the method.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Level 0: Place an overlay on the extended boundary ref with block 
	/// size set to the motion vec dim..
	_pExtRefOver = new OverlayExtMem2Dv2(_pExtRef,				// Src description. 
																		 _extWidth, 
																		 _extHeight,
																		 _macroBlkWidth,	// Block size description.
																		 _macroBlkHeight,
																		 _extBoundary,		// Boundary size for both left and right.
																		 _extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// Level 1: Ref mem at (_l1Width * _l1Height).
	_pRefL1 = new short[_l1Width * _l1Height];

	/// Level 1: Ref overlay with whole level 1 block dim.
	if(_pRefL1 != NULL)
	{
		_pRefL1Over = new OverlayMem2Dv2(_pRefL1, _l1Width, _l1Height, _l1Width, _l1Height);
		if(_pRefL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL1Over...
	}//end if _pRefL1...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 1: Extended ref mem _pExtRefL1 created by ExtendBoundary() call.
	_extL1Boundary = _l1MacroBlkWidth + MEH263IMCV2_L1_PADDING;
	if(_l1MacroBlkHeight > _l1MacroBlkWidth)
		_extL1Boundary = _l1MacroBlkHeight + MEH263IMCV2_L1_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL1, 
																			_l1Width,						
																			_l1Height, 
																			_extL1Boundary,
																			_extL1Boundary,
																			(void **)(&_pExtRefL1)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL1Width		= _l1Width + (2 * _extL1Boundary);
	_extL1Height	= _l1Height + (2 * _extL1Boundary);

	// Level 1: Ref overlay with level 1 motion block dim.
	_pExtRefL1Over = new OverlayExtMem2Dv2(_pExtRefL1, 
																			 _extL1Width,					// new mem width.
																			 _extL1Height,				// new mem height.
																			 _l1MacroBlkWidth,		// block width.
																			 _l1MacroBlkHeight,		// block height.
																			 _extL1Boundary,			// boundary width.
																			 _extL1Boundary);			// boundary height.
	if(_pExtRefL1Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL1Over...

	/// Level 2: Ref mem at (_l2Width * _l2Height).
	_pRefL2 = new short[_l2Width * _l2Height];

	/// Level 2: Ref overlay with whole level 2 block dim.
	if(_pRefL2 != NULL)
	{
		_pRefL2Over = new OverlayMem2Dv2(_pRefL2, _l2Width, _l2Height, _l2Width, _l2Height);
		if(_pRefL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL2Over...
	}//end if _pRefL2...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2: Extended ref mem _pExtRefL2 created by ExtendBoundary() call.
	_extL2Boundary = _l2MacroBlkWidth + MEH263IMCV2_L2_PADDING;
	if(_l2MacroBlkHeight > _l2MacroBlkWidth)
		_extL2Boundary = _l2MacroBlkHeight + MEH263IMCV2_L2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL2, 
																			_l2Width,						
																			_l2Height, 
																			_extL2Boundary,
																			_extL2Boundary,
																			(void **)(&_pExtRefL2)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL2Width		= _l2Width + (2 * _extL2Boundary);
	_extL2Height	= _l2Height + (2 * _extL2Boundary);

	/// Level 2: Ref overlay with level 2 motion block dim.
	_pExtRefL2Over = new OverlayExtMem2Dv2(_pExtRefL2, 
																			 _extL2Width,					// new mem width.
																			 _extL2Height,				// new mem height.
																			 _l2MacroBlkWidth,		// block width.
																			 _l2MacroBlkHeight,		// block height.
																			 _extL2Boundary,			// boundary width.
																			 _extL2Boundary);			// boundary height.
	if(_pExtRefL2Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL2Over...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half pel motion estimation and 
	/// compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																				_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	_ready = 1;
	return(1);
}//end Create.

void	MotionEstimatorH263ImplMultiresCrossVer2::Reset(void)
{
}//end Reset.

/** Set the speed mode.
This is a multresolution algorithm and the speed is increased by estimating
at lower levels but it is less accurate. Mode = 1 implies level 1 and mode = 2
for level 2. Mode = 0 is auto mode that selects an appropriate mode depending
on the resolution of the image. The selection is set to 2 if the image has
an area larger than 200x200.

@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void	MotionEstimatorH263ImplMultiresCrossVer2::SetMode(int mode)
 {
	if(mode == 0)	// Auto mode.
	{
		int area = _imgWidth * _imgHeight;
		if(area > 40000)
			_mode = 2;
		else
			_mode = 1;
	}//end if mode...
	else
		_mode = mode;
}//end SetMode.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries and a
absolute difference criterion. The mode setting (_mode) determines
the level of resolution.
@param pSrc		: Input image to estimate.
@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void* MotionEstimatorH263ImplMultiresCrossVer2::Estimate(long* avgDistortion)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH263IMCV2_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver is always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),		///< Src 2D ptr.
										  _imgWidth, 																///< Src width.
											_imgHeight, 															///< Src height.
											(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
												_l1Width, 																///< Src width.
												_l1Height, 																///< Src height.
												(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gathers the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< Half pel grid.
		int hmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.
    int predX, predY, predX0Rnd, predY0Rnd, predX1, predY1, predX2, predY2;
    _pMVPred->Get16x16Prediction(_pMotionVectorStruct, vecPos, &predX, &predY);
    int predXHalf = predX % 2;
    int predYHalf = predY % 2;
    int predX0    = predX / 2;
    int predY0    = predY / 2;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 1)/2;
    else
      predX0Rnd = (predX + 1)/2;
    if(predY < 0)
      predY0Rnd = (predY - 1)/2;
    else
      predY0Rnd = (predY + 1)/2;
    predX1   = predX0Rnd / 2; ///< Nearest level 1 pred motion vector.
    predY1   = predY0Rnd / 2;
    predX2   = predX1 / 2;    ///< Nearest level 2 pred motion vector.
    predY2   = predY1 / 2;

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute/square diff comparison method.
#ifdef MEH263IMCV2_ABS_DIFF
		int originVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int originVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
//#ifdef MEH263IMCV2_ABS_DIFF
//		int minDiff = _pInOver->Tad16x16(*_pExtRefOver);
//#else
//		int minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
//#endif
//#ifdef MEH263IMCV2_ABS_DIFF
//		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
//#else
//		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
//#endif
//		int minDiff			= zeroVecDiff;	///< Best so far.

		///----------------------- Level 2 cross pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks and compare with the pred motion vector as the baseline.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Absolute/square diff comparison method.
#ifdef MEH263IMCV2_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif
			
    	/// Level 2: Search on a full pel grid over the defined L2 motion range.

			/// Cross search loop.
			for(int w = _l2MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH263IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
                    int blkDiff;

					i = w * MEH263IMCV2_CrossPos[x].y;
					j = w * MEH263IMCV2_CrossPos[x].x;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH263IMCV2_LEVEL2_BREAK;

					/// Set the block to the (j,i) offset motion vector from the (mx,my) motion vector
					/// around the (l,k) reference location.
					_pExtRefL2Over->SetOrigin(j+l+mx, i+k+my);

#ifdef MEH263IMCV2_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4LessThan(*_pExtRefL2Over, minDiffL2);
#else
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif

					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest difference mv magnitude from the pred mv. 
						if(blkDiff == minDiffL2)
						{
              int currX = mx + rmx - predX2;
              int currY = my + rmy - predY2;
              int newX  = mx + j - predX2;
              int newY  = my + i + predY2;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
//							int vecDistDiff = ( (my*my)+(mx*mx) )-( (i*i)+(j*j) );
							if(vecDistDiff < 0)
								goto MEH263IMCV2_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...
			
					MEH263IMCV2_LEVEL2_BREAK: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

			mx = mx << 1; /// Convert level 2 to level 1 grid units ( x2 ).
			my = my << 1;
			
		}//end if _mode...

		///----------------------- Level 1 full/cross pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);
		/// Absolute diff comparison method.
#ifdef MEH263IMCV2_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Level 1: Search on a cross pel grid over the defined L1 motion range if mode != 2. The
		///					 range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;

		/// For mode = 2 (level 2 search has been done) do a refinement search.
		if(_mode == 2)
		{
			GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

			for(i = yuRng; i <= ydRng; i++)
			{
				for(j = xlRng; j <= xrRng; j++)
				{
                    int blkDiff;

					/// Early exit because zero (centre) motion vec already checked.
					if( !(i||j) )	goto MEH263IMCV2_LEVEL1_BREAK;

					/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMCV2_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude from the pred vector. 
						if(blkDiff == minDiffL1)
						{
              int currX = mx + rmx - predX1;
              int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;
              int newY  = my + i + predY1;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
//							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH263IMCV2_LEVEL1_BREAK;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH263IMCV2_LEVEL1_BREAK: ; ///< null.
				}//end for j...
			}//end for i...
		}//end if mode == 2...
		else	///< Do a cross search.
		{
			/// For this case, this is the first entry point of the search i.e. (mx,my) = (0,0).

			for(int w = _l1MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange-1, 1);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH263IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
					i = w * MEH263IMCV2_CrossPos[x].y;
					j = w * MEH263IMCV2_CrossPos[x].x;

                    int blkDiff;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH263IMCV2_LEVEL1_BREAK_C;

					/// Set the block to the (j,i) motion vector around the (mx+p,my+q) reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMCV2_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif

					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
              int currX = mx + rmx - predX1;
              int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;
              int newY  = my + i + predY1;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
//							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH263IMCV2_LEVEL1_BREAK_C;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH263IMCV2_LEVEL1_BREAK_C: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...
		}//end else...

		mx = (mx+rmx) * 2; ///< Convert level 1 to level 0 grid units ( x2 ) and add the refinement.
		my = (my+rmy) * 2;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range.

		/// Get the min diff at this location in level 0 grid units.
		_pExtRefOver->SetOrigin(n+mx,m+my);

#ifdef MEH263IMCV2_ABS_DIFF
		int minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH263IMCV2_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
      for(j = xlRng; j <= xrRng; j++)
      {
                int blkDiff;

				/// Early exit because zero offset motion vec already checked.
				if( !(i||j) )	goto MEH263IMCV2_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH263IMCV2_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
//				int blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global motion vector magnitude. 
					if(blkDiff == minDiff)
					{
            int currX = mx + rmx - predX0Rnd;
            int currY = my + rmy - predY0Rnd;
            int newX  = mx + j - predX0Rnd;
            int newY  = my + i + predY0Rnd;
						int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
//						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
						if(vecDistDiff < 0)
							goto MEH263IMCV2_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH263IMCV2_LEVEL0_BREAK: ; ///< null.
      }//end for j...
    }//end for i...

		/// Add the refinement.
		mx += rmx;
		my += rmy;

		///----------------------- Level 0 half pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a half pel grid.

		/// Set the location to the current min diff motion vector [mx,my].
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// The half pel motion search is split into two steps. Firstly, find the best corner
		/// position and then, secondly, refine this with each cross located pel around the
		/// winner. Note that a full cross will be required if the (0,0) vector remains the
		/// best.
		/// ---------- Step 1 -------------------------
		int bestCorner = 0;
    for(int corner = 0; corner < MEH263IMCV2_MOTION_HALF_CORNER_POS_LENGTH; corner++)
    {
			int hOffX = MEH263IMCV2_HalfCornerPos[corner].x;
			int hOffY = MEH263IMCV2_HalfCornerPos[corner].y;

			/// Read the half grid pels into temp.
			_pExtRefOver->HalfRead(*_pMBlkOver, hOffX, hOffY);

#ifdef MEH263IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				bestCorner	= corner;
				minDiff			= blkDiff;
				hmx					= hOffX;
				hmy					= hOffY;
			}//end if blkDiff...
    }//end for corner...

		/// ---------- Step 2 -------------------------
		MEH263IMCV2_COORD*	pattern			= MEH263IMCV2_HalfRefinedPos[bestCorner];
		int								patternLen	= MEH263IMCV2_MOTION_HALF_REFINED_POS_LENGTH;
		/// If no corner was better than the (0,0) half pos then do a full cross.
		if( !hmx && !hmy )
		{
			pattern			= MEH263IMCV2_CrossPos;
			patternLen	= MEH263IMCV2_MOTION_CROSS_POS_LENGTH;
		}//end if !hmx...
    for(int cross = 0; cross < patternLen; cross++)
    {
			int hOffX = pattern[cross].x;
			int hOffY = pattern[cross].y;

			/// Read the half grid pels into temp.
			_pExtRefOver->HalfRead(*_pMBlkOver, hOffX, hOffY);

#ifdef MEH263IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = hOffX;
				hmy = hOffY;
			}//end if blkDiff...
    }//end for cross...

		/// Add the refinement in half pel units.
		int mvx = (mx << 1) + hmx;
		int mvy = (my << 1) + hmy;

		/// Bounds check used for debugging only as minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx > (_motionRange-1))
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy > (_motionRange-1))
		//	mvy = (_motionRange-1);

    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 2) + predXHalf;
    predY = (predY0 * 2) + predYHalf;

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int zeroVecDiff = 0;

    if(predXHalf || predYHalf)
    {
			/// Read the half grid pels into temp.
			_pExtRefOver->HalfRead(*_pMBlkOver, predXHalf, predYHalf);
		  /// Absolute/square diff comparison method.
#ifdef MEH263IMCV2_ABS_DIFF
		  zeroVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  zeroVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
#endif
    }//end if predXHalf...
    else
    {
		  /// Absolute/square diff comparison method.
#ifdef MEH263IMCV2_ABS_DIFF
		  zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end else...

		/// Selection of the final motion vector is weighted with non-linear factors. The
    /// zero vector will be modified to the best of either the predicted mv or the zero mv.
		int magSqr	= (mvx * mvx) + (mvy * mvy);
    int zeromvx = predX;
    int zeromvy = predY;
    if(originVecDiff < zeroVecDiff)
    {
      zeroVecDiff = originVecDiff;
      zeromvx     = 0;
      zeromvy     = 0;
    }//end if predVecDiff...

		int weight						= 0;
		int diffWithZeroDiff	= zeroVecDiff - minDiff;

#ifdef MEH263IMCV2_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff >> 1) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH263IMCV2_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff >> 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH263IMCV2_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

/*
		/// Determine the final winning motion vector from the found mv, the perd mv and the zero mv.
		if((minDiff < zeroVecDiff)&&(minDiff < originVecDiff))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
      if(zeroVecDiff <= originVecDiff)
      {
			  mvx = predX;
			  mvy = predY;
			  if(doIt)
				  totalDifference += zeroVecDiff;
      }//end if zeroVecDiff...
      else
      {
			  mvx = 0;
			  mvy = 0;
			  if(doIt)
				  totalDifference += originVecDiff;
      }//end else...
		}//end else...
*/
		/// Decide whether or not to accept the final motion vector or revert to the zero/pred motion vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = zeromvx;
			mvy = zeromvy;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH263ImplMultiresCrossVer2::Destroy(void)
{
	_ready = 0;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pInL1 != NULL)
		delete[] _pInL1;
	_pInL1 = NULL;

	if(_pInL1Over != NULL)
		delete _pInL1Over;
	_pInL1Over = NULL;

	if(_pInL2 != NULL)
		delete[] _pInL2;
	_pInL2 = NULL;

	if(_pInL2Over != NULL)
		delete _pInL2Over;
	_pInL2Over = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pRefL1 != NULL)
		delete[] _pRefL1;
	_pRefL1	= NULL;

	if(_pRefL1Over != NULL)
		delete _pRefL1Over;
	_pRefL1Over	= NULL;

	if(_pExtRefL1 != NULL)
		delete[] _pExtRefL1;
	_pExtRefL1 = NULL;

	if(_pExtRefL1Over != NULL)
		delete _pExtRefL1Over;
	_pExtRefL1Over = NULL;

	if(_pRefL2 != NULL)
		delete[] _pRefL2;
	_pRefL2	= NULL;

	if(_pRefL2Over != NULL)
		delete _pRefL2Over;
	_pRefL2Over	= NULL;

	if(_pExtRefL2 != NULL)
		delete[] _pExtRefL2;
	_pExtRefL2 = NULL;

	if(_pExtRefL2Over != NULL)
		delete _pExtRefL2Over;
	_pExtRefL2Over = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.263 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed x left range.
@param xrr			: Returned allowed x right range.
@param yur			: Returned allowed y up range.
@param ydr			: Returned allowed y down range.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH263ImplMultiresCrossVer2::GetMotionRange(int  x,			int  y, 
																									int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range,	int	 level)
{
	// The level defines the members to use.
	int boundary, width, height;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary;
			width			= _l1Width;
			height		= _l1Height;
			break;
		case 2 :
			boundary	= _extL2Boundary;
			width			= _l2Width;
			height		= _l2Height;
			break;
		case 0 :
		default :
			boundary	= _extBoundary;
			width			= _imgWidth;
			height		= _imgHeight;
			break;
	}//end switch level...

	if( (x - range) >= -boundary )	// Ok and within left extended boundary.
		*xlr = -range;
	else // Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	// Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	// Ok and within upper extended boundary.
		*yur = -range;
	else // Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	// Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH263ImplMultiresCrossVer2::GetMotionRange(	int  xpos,	int  ypos,
																														int	 xoff,	int  yoff,
																														int* xlr,		int* xrr, 
																														int* yur,		int* ydr,
																														int	 range,	int	 level)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	/// The level defines the members to use.
	int boundary, width, height, vecRange;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH263IMCV2_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			vecRange	= _l1MotionRange;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH263IMCV2_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			vecRange	= _l2MotionRange;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH263IMCV2_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			vecRange	= _motionRange/2;	///< Convert 1/2 pel range to full pel units.
			break;
	}//end switch level...

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.




========== END FILE: CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.h ==========
Bundle entry: 86
Original bytes: 8962
Original SHA-256: f4813982766cd69db663f0fb1419787ebda48913a9e57b7406adcc22c22b0495
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH263ImplMultiresCrossVer2

TAG						: MEH263IMCV2

FILE NAME			: MotionEstimatorH263ImplMultiresCrossVer2.h

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.263 (02/98) Annex D page 53 of absolute 
								error difference measure.	Access via a IMotionEstimator	
								interface. There are 2 mode levels of execution speed vs. 
								quality. At the lowest resolution a converging cross search
								method is used to find the best block match. The boundary 
								is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH263IMPLMULTIRESCROSSVER2_H
#define _MOTIONESTIMATORH263IMPLMULTIRESCROSSVER2_H

#include "IMotionEstimator.h"
#include "VectorStructList.h"
#include "IMotionVectorPredictor.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH263IMCV2_COORD
{
	short int x;
	short int y;
} MEH263IMCV2_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH263ImplMultiresCrossVer2 : public IMotionEstimator
{
// Construction.
public:

	MotionEstimatorH263ImplMultiresCrossVer2(	const void*             pSrc, 
																				    const void*             pRef, 
																				    int					            imgWidth, 
																				    int					            imgHeight,
																				    int					            motionRange,
                                            IMotionVectorPredictor* pMVPred);

	MotionEstimatorH263ImplMultiresCrossVer2(	const void*             pSrc, 
																				    const void*             pRef, 
																				    int					            imgWidth, 
																				    int					            imgHeight,
																				    int					            motionRange,
                                            IMotionVectorPredictor* pMVPred,
																				    void*				            pDistortionIncluded);

	virtual ~MotionEstimatorH263ImplMultiresCrossVer2(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
	virtual void	Reset(void);
	virtual int		Ready(void)		{ return(_ready); }
	virtual void	SetMode(int mode);
	virtual int		GetMode(void) { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 

protected:

	int _ready;	// Ready to estimate.
	int _mode;	// Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				// Width of the src and ref images. 
	int	_imgHeight;				// Height of the src and ref images.
	int	_macroBlkWidth;		// Width of the motion block.
	int	_macroBlkHeight;	// Height of the motion block.
	int	_motionRange;			// (x,y) range of the motion vectors.

	const void*	_pInput;	// References to the images at construction.
	const void* _pRef;

	// Level 0: Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					// Input overlay with motion block dim.
	// Level 1: Subsampled input by 2. [_mode == 1]
	short*						_pInL1;						// Input mem at (_l1Width * _l1Height).
	int								_l1Width;
	int								_l1Height;
	int								_l1MacroBlkWidth;
	int								_l1MacroBlkHeight;
	int								_l1MotionRange;
	OverlayMem2Dv2*		_pInL1Over;				// Input overlay with level 1 motion block dim.
	// Level 2: Subsampled input by 4.	[_mode == 2]
	short*						_pInL2;						// Input mem at (_l2Width * _l2Height).
	int								_l2Width;
	int								_l2Height;
	int								_l2MacroBlkWidth;
	int								_l2MacroBlkHeight;
	int								_l2MotionRange;
	OverlayMem2Dv2*		_pInL2Over;				// Input overlay with level 2 motion block dim.

	// Level 0: Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				// Ref overlay with whole block dim.
	short*							_pExtRef;					// Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			// Extended ref overlay with motion block dim.
	// Level 1: Subsampled ref by 2.		[_mode == 1]
	short*							_pRefL1;					// Ref mem at (_l1Width * _l1Height).
	OverlayMem2Dv2*			_pRefL1Over; 			// Ref overlay with whole level 1 block dim.
	short*							_pExtRefL1;				// Extended ref mem create by ExtendBoundary() call.
	int									_extL1Width;
	int									_extL1Height;
	int									_extL1Boundary;		// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL1Over;		// Ref overlay with level 1 motion block dim.
	// Level 2: Subsampled ref by 4.		[_mode == 2]
	short*							_pRefL2;					// Ref mem at (_l2Width * _l2Height).
	OverlayMem2Dv2*			_pRefL2Over; 			// Ref overlay with whole level 2 block dim.
	short*							_pExtRefL2;				// Extended ref mem create by ExtendBoundary() call.
	int									_extL2Width;
	int									_extL2Height;
	int									_extL2Boundary;		// Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL2Over;		// Ref overlay with level 2 motion block dim.

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	      _pMotionVectorStruct;
  /// Attached motion vector predictor on construction.
  IMotionVectorPredictor* _pMVPred;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH263ImplMultiresCrossVer2.


#endif // !_MOTIONESTIMATORH263IMPLMULTIRESCROSSVER2_H

========== END FILE: CodecUtils/MotionEstimatorH263ImplMultiresCrossVer2.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplCross.cpp ==========
Bundle entry: 87
Original bytes: 43022
Original SHA-256: a3d2444cfdd534ac8a033448d5e5c8a9c3e8d297965d05afb1cf5a78de026f6b
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplCross

TAG						: MEH264IC

FILE NAME			: MotionEstimatorH264ImplCross.cpp

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2016 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplCross.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IC_FULL_MOTION_NOISE_FLOOR				512
#define MEH264IC_MOTION_NOISE_FLOOR							 26 //24 //sqrt 512

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. 
#define MEH264IC_PADDING													3	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IC_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IC_MOTION_SUB_POS_LENGTH 	8
MEH264IC_COORD MEH264IC_SubPos[MEH264IC_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH264IC_MOTION_CROSS_POS_LENGTH 	4
MEH264IC_COORD MEH264IC_CrossPos[MEH264IC_MOTION_CROSS_POS_LENGTH] =
{
  { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 }
};

const MEH264IC_COORD MotionEstimatorH264ImplCross::MEH264IC_OptimalPath[] =
{
  {  5,10 },{ 13, 5 },{  2, 1 },{ 13,14 },{  1,14 },{  9, 1 },{ 15, 9 },{  8,13 },{ 14, 2 },{  7, 4 },{ 10, 8 },{  4,15 },{  0,10 },{  0, 3 },{  5, 0 },{ 12,11 },
  {  4, 7 },{ 12, 0 },{ 10,14 },{  3,12 },{ 10, 5 },{ 15,13 },{  4, 3 },{  7, 8 },{  6,13 },{  2, 9 },{  9,10 },{ 15, 1 },{  7, 2 },{  3, 5 },{  8,15 },{  1,12 },
  {  8, 6 },{  0, 1 },{ 12, 9 },{ 14,15 },{ 15, 4 },{ 11,12 },{  6, 6 },{  7,11 },{  0, 7 },{ 14,11 },{  7, 0 },{  2,15 },{ 12, 7 },{  2, 3 },{  4, 9 },{ 12, 2 },
  {  9, 3 },{ 12,13 },{  3, 0 },{  5,14 },{  5, 4 }
};

const MEH264IC_COORD MotionEstimatorH264ImplCross::MEH264IC_LinearPath[] =
{
  {  0, 0 },{  0, 1 },{  0, 2 },{  0, 3 },{  0, 4 },{  0, 5 },{  0, 6 },{  0, 7 },{  0, 8 },{  0, 9 },{  0,10 },{  0,11 },{  0,12 },{ 0,13 },{ 0,14 },{ 0,15 }, ///< 0-15
  {  1, 0 },{  1, 1 },{  1, 2 },{  1, 3 },{  1, 4 },{  1, 5 },{  1, 6 },{  1, 7 },{  1, 8 },{  1, 9 },{  1,10 },{  1,11 },{  1,12 },{ 1,13 },{ 1,14 },{ 1,15 }, ///< 16-31
  {  2, 0 },{  2, 1 },{  2, 2 },{  2, 3 },{  2, 4 },{  2, 5 },{  2, 6 },{  2, 7 },{  2, 8 },{  2, 9 },{  2,10 },{  2,11 },{  2,12 },{ 2,13 },{ 2,14 },{ 2,15 }, ///< 32-47
  {  3, 0 },{  3, 1 },{  3, 2 },{  3, 3 },{  3, 4 },{  3, 5 },{  3, 6 },{  3, 7 },{  3, 8 },{  3, 9 },{  3,10 },{  3,11 },{  3,12 },{ 3,13 },{ 3,14 },{ 3,15 }, ///< 48-63
  {  4, 0 },{  4, 1 },{  4, 2 },{  4, 3 },{  4, 4 },{  4, 5 },{  4, 6 },{  4, 7 },{  4, 8 },{  4, 9 },{  4,10 },{  4,11 },{  4,12 },{ 4,13 },{ 4,14 },{ 4,15 }, ///< 64-79
  {  5, 0 },{  5, 1 },{  5, 2 },{  5, 3 },{  5, 4 },{  5, 5 },{  5, 6 },{  5, 7 },{  5, 8 },{  5, 9 },{  5,10 },{  5,11 },{ 5,12 },{ 5,13 },{ 5,14 },{ 5,15 }, ///< 80-95
  {  6, 0 },{  6, 1 },{  6, 2 },{  6, 3 },{  6, 4 },{  6, 5 },{  6, 6 },{  6, 7 },{  6, 8 },{  6, 9 },{  6,10 },{  6,11 },{ 6,12 },{ 6,13 },{ 6,14 },{ 6,15 }, ///< 96-111
  {  7, 0 },{  7, 1 },{  7, 2 },{  7, 3 },{  7, 4 },{  7, 5 },{  7, 6 },{  7, 7 },{  7, 8 },{  7, 9 },{  7,10 },{  7,11 },{ 7,12 },{ 7,13 },{ 7,14 },{ 7,15 }, ///< 112-127
  {  8, 0 },{  8, 1 },{  8, 2 },{  8, 3 },{  8, 4 },{  8, 5 },{  8, 6 },{  8, 7 },{  8, 8 },{  8, 9 },{  8,10 },{  8,11 },{ 8,12 },{ 8,13 },{ 8,14 },{ 8,15 }, ///< 128-143
  {  9, 0 },{  9, 1 },{  9, 2 },{  9, 3 },{  9, 4 },{  9, 5 },{  9, 6 },{  9, 7 },{  9, 8 },{  9, 9 },{  9,10 },{  9,11 },{ 9,12 },{ 9,13 },{ 9,14 },{ 9,15 }, ///< 144-159
  { 10, 0 },{ 10, 1 },{ 10, 2 },{ 10, 3 },{ 10, 4 },{ 10, 5 },{ 10, 6 },{ 10, 7 },{ 10, 8 },{ 10, 9 },{ 10,10 },{ 10,11 },{ 10,12 },{ 10,13 },{ 10,14 },{ 10,15 }, ///< 160-175
  { 11, 0 },{ 11, 1 },{ 11, 2 },{ 11, 3 },{ 11, 4 },{ 11, 5 },{ 11, 6 },{ 11, 7 },{ 11, 8 },{ 11, 9 },{ 11,10 },{ 11,11 },{ 11,12 },{ 11,13 },{ 11,14 },{ 11,15 }, ///< 176-191
  { 12, 0 },{ 12, 1 },{ 12, 2 },{ 12, 3 },{ 12, 4 },{ 12, 5 },{ 12, 6 },{ 12, 7 },{ 12, 8 },{ 12, 9 },{ 12,10 },{ 12,11 },{ 12,12 },{ 12,13 },{ 12,14 },{ 12,15 }, ///< 192-207
  { 13, 0 },{ 13, 1 },{ 13, 2 },{ 13, 3 },{ 13, 4 },{ 13, 5 },{ 13, 6 },{ 13, 7 },{ 13, 8 },{ 13, 9 },{ 13,10 },{ 13,11 },{ 13,12 },{ 13,13 },{ 13,14 },{ 13,15 }, ///< 208-223
  { 14, 0 },{ 14, 1 },{ 14, 2 },{ 14, 3 },{ 14, 4 },{ 14, 5 },{ 14, 6 },{ 14, 7 },{ 14, 8 },{ 14, 9 },{ 14,10 },{ 14,11 },{ 14,12 },{ 14,13 },{ 14,14 },{ 14,15 }, ///< 224-239
  { 15, 0 },{ 15, 1 },{ 15, 2 },{ 15, 3 },{ 15, 4 },{ 15, 5 },{ 15, 6 },{ 15, 7 },{ 15, 8 },{ 15, 9 },{ 15,10 },{ 15,11 },{ 15,12 },{ 15,13 },{ 15,14 },{ 15,15 }  ///< 240-255
};

/// Num of items in the Fifos.
#define MEH264IC_FIFO_LENGTH 5

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IC_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplCross::MotionEstimatorH264ImplCross(	const void*             pSrc, 
																													  const void*             pRef, 
																													  int					            imgWidth, 
																													  int					            imgHeight,
																													  int					            motionRange,
                                                            IMotionVectorPredictor* pMVPred)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;
  _pMVPred        = pMVPred;

}//end constructor.

MotionEstimatorH264ImplCross::MotionEstimatorH264ImplCross(	const void*             pSrc, 
																													  const void*             pRef, 
																													  int					            imgWidth, 
																													  int					            imgHeight,
																													  int					            motionRange,
                                                            IMotionVectorPredictor* pMVPred,
																													  void*				            pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
  _pMVPred              = pMVPred;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplCross::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with mb motion block dim.
	/// Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
  /// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;
  /// Attached motion vector predictor on construction.
  _pMVPred             = NULL;

  /// Set up the fifos.
  _xVector.Create(MEH264IC_FIFO_LENGTH);
  _yVector.Create(MEH264IC_FIFO_LENGTH);
  _distVector.Create(MEH264IC_FIFO_LENGTH);

  /// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;

  /// Number of locations to test for partial sums along a path.
//  _pathLength = 53;
  _pathLength = 48;
}//end ResetMembers.

MotionEstimatorH264ImplCross::~MotionEstimatorH264ImplCross(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplCross::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Put an overlay on the input image with the block size set to the mb vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((short *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// --------------- Configure ref overlays --------------------------------
	/// Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore create its own mem.
	_pRefOver = new OverlayMem2Dv2((short *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock plus some padding to cater for quarter pel
  /// searches on the edges of the boundary. The mem is allocated in the method call.
	_extBoundary = _macroBlkWidth + MEH264IC_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IC_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Place an overlay on the extended boundary ref with block size set to the mb motion 
  /// vec dim.
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description created in the ExtendBoundary() call. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half/quarter pel motion 
  /// estimation and compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= ((6 + _macroBlkWidth) * 4);
	int winHeight = ((6 + _macroBlkHeight) * 4);
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((short *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	_ready = 1;
	return(1);
}//end Create.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in the implementation. 
The returned type holds the vectors. This is a telescopic cross search algorithm with 
extended boundaries with a choice of absolute difference or squared difference criterioa. 
@param avgDistortion  : Return the motion compensated distortion.
@return				        : The list of motion vectors.
*/
void* MotionEstimatorH264ImplCross::Estimate(long* avgDistortion)
{
  int		i,j,m,n;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Write the ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
  for(m = 0; m < _imgHeight; m += _macroBlkHeight)
		for(n = 0; n < _imgWidth; n += _macroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.
    int predX, predY, predX0Rnd, predY0Rnd;
    _pMVPred->Get16x16Prediction(NULL, vecPos, &predX, &predY);
    int predXQuart  = predX % 4;
    int predYQuart  = predY % 4;
    int predX0      = predX / 4;
    int predY0      = predY / 4;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 2)/4;
    else
      predX0Rnd = (predX + 2)/4;
    if(predY < 0)
      predY0Rnd = (predY - 2)/4;
    else
      predY0Rnd = (predY + 2)/4;

		/// Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// The (0,0) vector is the one to beat with Absolute/Square diff comparison method.
#ifdef MEH264IC_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		//int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
    //int zeroVecDiff = _pInOver->Tsd16x16PartialPath(*_pExtRefOver, (void *)MEH264IC_LinearPath, _pathLength);
    int zeroVecDiff = _pInOver->Tsd16x16PartialPath(*_pExtRefOver, (void *)MEH264IC_OptimalPath, _pathLength);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far.

    ///--------------------------- Full pel cross grid search ---------------------------------------------------
    /// From this mb position determine the full pel search range permitted for the motion vector.
    int mRng = _motionRange/4;  ///< _motionRange is in 1/4 pel units and must be converted to full pel units.
		GetMotionRange(n, m, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, mRng);

    /// Start at half the motion range and then converge by halving on every iteration. Note that
    /// it is assumed that the motion vector range is an even number of full pels.
    for(int w = mRng/2; w > 0; w = w/2) 
		{
      /// Reset the offset from [mx,my].
      rmx = 0;
      rmy = 0;
      for (int x = 0; x < MEH264IC_MOTION_CROSS_POS_LENGTH; x++)
      {
        i = w * MEH264IC_CrossPos[x].y;
        j = w * MEH264IC_CrossPos[x].x;

        int blkDiff = 0;
        /// Check that this offset is within the range of the image boundaries. If not then skip.
        if (((i + my) < yuRng) || ((i + my) > ydRng) || ((j + mx) < xlRng) || ((j + mx) > xrRng))
          goto MEH264IC_FULL_BREAK;

        /// Set the block to the [j,i] offset motion vector from the [mx,my] motion vector around 
        /// the [n,m] reference location.
        _pExtRefOver->SetOrigin(n + j + mx, m + i + my);

#ifdef MEH264IC_ABS_DIFF
        int blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
        //int blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
        //int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
        //int blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pExtRefOver, (void *)MEH264IC_LinearPath, _pathLength, minDiff);
        blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pExtRefOver, (void *)MEH264IC_OptimalPath, _pathLength, minDiff);
#endif
        if (blkDiff <= minDiff)
        {
          /// Weight the equal diff case with the smallest global mv magnitude from the pred mv. 
          if (blkDiff == minDiff)
          {
            int currX = mx + rmx - predX0Rnd;
            int currY = my + rmy - predY0Rnd;
            int newX = mx + j - predX0Rnd;
            int newY = my + i - predY0Rnd;
            int vecDistDiff = ((currY*currY) + (currX*currX)) - ((newY*newY) + (newX*newX));
            if (vecDistDiff < 0)
              goto MEH264IC_FULL_BREAK;
          }//end if blkDiff...

          minDiff = blkDiff;
          rmx = j;
          rmy = i;
        }//end if blkDiff...

        MEH264IC_FULL_BREAK:; ///< null.
      }//end for x...

      /// Update centre of winning vector.
      mx += rmx;
      my += rmy;

    }//end for w...

		///----------------------- Quarter pel refined search ----------------------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector (mx,my).
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IC_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IC_SubPos[x].x;
			int qOffY = 2 * MEH264IC_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
		//int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
		//int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
    //int blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pExtRefOver, (void *)MEH264IC_LinearPath, _pathLength, minDiff);
    int blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pMBlkOver, (void *)MEH264IC_OptimalPath, _pathLength, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IC_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IC_SubPos[x].x;
			int qOffY = hmy + MEH264IC_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
      //int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
			//int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
      //int blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pExtRefOver, (void *)MEH264IC_LinearPath, _pathLength, minDiff);
      int blkDiff = _pInOver->Tsd16x16PartialPathLessThan(*_pMBlkOver, (void *)MEH264IC_OptimalPath, _pathLength, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		///----------------------- Quarter pel pred vector ----------------------------
    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 4) + predXQuart;
    predY = (predY0 * 4) + predYQuart;

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int predVecDiff = 0;
    /// Quarter read first if necessary.
    if(predXQuart || predYQuart)
    {
			/// Read the quarter grid pels into temp.
			_pExtRefOver->QuarterRead(*_pMBlkOver, predXQuart, predYQuart);
		/// Absolute/square diff comparison method.
#ifdef MEH264IC_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  //predVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
      //predVecDiff = _pInOver->Tsd16x16PartialPath(*_pMBlkOver, (void *)MEH264IC_LinearPath, _pathLength);
      predVecDiff = _pInOver->Tsd16x16PartialPath(*_pMBlkOver, (void *)MEH264IC_OptimalPath, _pathLength);
#endif
    }//end if predXQuart...
    else
    {
#ifdef MEH264IC_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  //predVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
      //predVecDiff = _pInOver->Tsd16x16PartialPath(*_pExtRefOver, (void *)MEH264IC_LinearPath, _pathLength);
      predVecDiff = _pInOver->Tsd16x16PartialPath(*_pExtRefOver, (void *)MEH264IC_OptimalPath, _pathLength);
#endif
    }//end else...

     /// Initialise the fifos and load the zero vector, pred vector and the curr best vector.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn(0.0); _yVector.AddFirstIn(0.0); _distVector.AddFirstIn((double)zeroVecDiff);
    _xVector.AddFirstIn((double)predX); _yVector.AddFirstIn((double)predY); _distVector.AddFirstIn((double)predVecDiff);
    _xVector.AddFirstIn((double)mvx); _yVector.AddFirstIn((double)mvy); _distVector.AddFirstIn((double)minDiff);
    /// Make a Legrange multiplier based selection for a more optimal motion vector.
    int vpos = GetBestVector(&_distVector, &_xVector, &_yVector, 0.9, (double)_pathLength, predX, predY, &mvx, &mvy);

    /// Check for inclusion in the distortion calculation.
    if (_pDistortionIncluded != NULL)
    {
      mvx = (int)_xVector.GetItem(vpos);
      mvy = (int)_yVector.GetItem(vpos);
      if (_pDistortionIncluded[vecPos])
      {
        included++;
        totalDifference += (int)_distVector.GetItem(vpos);
      }//end if _pDistortionIncluded...
    }//end if _pDistortionIncluded...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
      /// Set macroblock vector for future predictions.
      _pMVPred->Set16x16MotionVector(vecPos, mvx, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplCross::Destroy(void)
{
	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplCross::GetMotionRange( int  x,			int  y, 
																								  int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int boundary	= _extBoundary - MEH264IC_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplCross::GetMotionRange(	int  xpos,	int  ypos,
																									int	 xoff,	int  yoff,
																									int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	int boundary	= _extBoundary - MEH264IC_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;
	int	vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplCross::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IC_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IC_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IC_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...

    /// One further "h" and "G" col at the end of the row.
		/// "h"
		window[quartRow+2][quartCol] = MEH264IC_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];

	}//end fullRow...

   /// One further "b" and "G" row at the end.
	for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
	{
		/// "b"
		window[quartRow][quartCol+2] = MEH264IC_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];
	}//end for fullCol...

  /// ...and one final "G" full pel at the bottom right edge.
	window[quartRow][quartCol] = ref[refRow][refCol];

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplCross::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplCross::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.






========== END FILE: CodecUtils/MotionEstimatorH264ImplCross.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplCross.h ==========
Bundle entry: 88
Original bytes: 9022
Original SHA-256: d2fec4734b0f049b58c00b95ace411b037306d630503f8f062149b2120ad869e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplCross

TAG						: MEH264IC

FILE NAME			: MotionEstimatorH264ImplCross.h

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2016 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLCROSS_H
#define _MOTIONESTIMATORH264IMPLCROSS_H

#include "IMotionEstimator.h"
#include "IMotionVectorPredictor.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"
#include "GeneralUtils/Fifo.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IC_COORD
{
	short int x;
	short int y;
} MEH264IC_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplCross : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplCross(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred);

	MotionEstimatorH264ImplCross(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred,
																void*				            pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplCross(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
  virtual void	Reset(void)       {}
	virtual int		Ready(void)		    { return(_ready); }
  virtual void	SetMode(int mode) { _mode = mode; }
	virtual int		GetMode(void)     { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

  /// Select the vector that minimised a cost function from a list of x, y and distortion ordered vectors. The
  /// euclidian distance is measured from a reference vector. Return the list index of the 
  /// smallest vector. The values of mx & my are assumed to be copies of the vector from the top
  /// of the list at pos = 0.
  int GetBestVector(Fifo* d, Fifo* x, Fifo* y, double lambda, double norm, int xref, int yref, int* mx, int* my)
  {
    int pos = 0;
    int vecLen = (int)x->GetLength();  ///< Assume d, x & y have the same length.
    double currMag = (double)((((*mx) - xref)*((*mx) - xref)) + (((*my) - yref)*((*my) - yref)));
    double currDist = d->GetItem(0);
    double currCost = (currDist / norm) + (lambda*sqrt(currMag));

    for (int ii = 1; ii < vecLen; ii++)
    {
      int xVec = (int)x->GetItem(ii);
      int yVec = (int)y->GetItem(ii);
      double newMag = (double)(((xVec - xref)*(xVec - xref)) + ((yVec - yref)*(yVec - yref)));
      double newDist = d->GetItem(ii);
      double newCost = (newDist / norm) + (lambda*sqrt(newMag));
      if (newCost < currCost)
      {
        (*mx) = xVec;
        (*my) = yVec;
        currMag = newMag;
        currDist = newDist;
        currCost = newCost;
        pos = ii;
      }//end if newCost...

    }//end for ii...

    return(pos);
  }//end GetBestVector.

protected:
  int _pathLength;
  const static MEH264IC_COORD MEH264IC_OptimalPath[53];
  const static MEH264IC_COORD MEH264IC_LinearPath[256];

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.

	/// Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.

	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

  /// Fifos to store intermediate results.
  Fifo  _xVector;
  Fifo  _yVector;
  Fifo  _distVector;

  /// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;
  /// Attached motion vector predictor on construction.
  IMotionVectorPredictor* _pMVPred;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH264ImplCross.

#endif // !_MOTIONESTIMATORH264IMPLCROSS_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplCross.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplFull.cpp ==========
Bundle entry: 89
Original bytes: 37403
Original SHA-256: 9cd37352f7aa30259c7d1e260e8c5a197273ac45a0c54fb21b1ee63103e975b6
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplFull

TAG						: MEH264IF

FILE NAME			: MotionEstimatorH264ImplFull.cpp

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplFull.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IF_FULL_MOTION_NOISE_FLOOR				512
#define MEH264IF_MOTION_NOISE_FLOOR							 26 //24 //sqrt 512

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. 
#define MEH264IF_PADDING													3	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IF_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IF_MOTION_SUB_POS_LENGTH 	8
MEH264IF_COORD MEH264IF_SubPos[MEH264IF_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IF_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplFull::MotionEstimatorH264ImplFull(	const void*             pSrc, 
																													const void*             pRef, 
																													int					            imgWidth, 
																													int					            imgHeight,
																													int					            motionRange,
                                                          IMotionVectorPredictor* pMVPred)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;
  _pMVPred        = pMVPred;

}//end constructor.

MotionEstimatorH264ImplFull::MotionEstimatorH264ImplFull(	const void*             pSrc, 
																													const void*             pRef, 
																													int					            imgWidth, 
																													int					            imgHeight,
																													int					            motionRange,
                                                          IMotionVectorPredictor* pMVPred,
																													void*				            pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
  _pMVPred              = pMVPred;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplFull::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with mb motion block dim.
	/// Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
  /// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;
  /// Attached motion vector predictor on construction.
  _pMVPred             = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH264ImplFull::~MotionEstimatorH264ImplFull(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplFull::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Put an overlay on the input image with the block size set to the mb vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((void *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// --------------- Configure ref overlays --------------------------------
	/// Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore create its own mem.
	_pRefOver = new OverlayMem2Dv2((void *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock plus some padding to cater for quarter pel
  /// searches on the edges of the boundary. The mem is allocated in the method call.
	_extBoundary = _macroBlkWidth + MEH264IF_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IF_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Place an overlay on the extended boundary ref with block size set to the mb motion 
  /// vec dim.
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description created in the ExtendBoundary() call. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half/quarter pel motion 
  /// estimation and compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= ((6 + _macroBlkWidth) * 4);
	int winHeight = ((6 + _macroBlkHeight) * 4);
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((void *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	_ready = 1;
	return(1);
}//end Create.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a full search algorithm with extended boundaries with a choice of
absolute difference or squared difference criterioa. 
@param avgDistortion  : Return the motion compensated distortion.
@return				        : The list of motion vectors.
*/
void* MotionEstimatorH264ImplFull::Estimate(long* avgDistortion)
{
  int		i,j,m,n;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Write the ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
  for(m = 0; m < _imgHeight; m += _macroBlkHeight)
		for(n = 0; n < _imgWidth; n += _macroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.
    int predX, predY, predX0Rnd, predY0Rnd;
    _pMVPred->Get16x16Prediction(NULL, vecPos, &predX, &predY);
    int predXQuart  = predX % 4;
    int predYQuart  = predY % 4;
    int predX0      = predX / 4;
    int predY0      = predY / 4;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 2)/4;
    else
      predX0Rnd = (predX + 2)/4;
    if(predY < 0)
      predY0Rnd = (predY - 2)/4;
    else
      predY0Rnd = (predY + 2)/4;

		/// Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// The (0,0) vector is the one to beat with Absolute/Square diff comparison method.
#ifdef MEH264IF_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far.

    ///--------------------------- Full pel full grid search ---------------------------------------------------
    /// From this mb position determine the full pel search range permitted for the motion vector.
		GetMotionRange(n, m, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _motionRange/4); ///< _motionRange is in 1/4 pel units and must be converted.

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
				int blkDiff;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IF_FULL_BREAK;

				/// Set the block to the [j,i] motion vector around the [n,m] reference location.
				_pExtRefOver->SetOrigin(n+j, m+i);

#ifdef MEH264IF_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
//				blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff case with the smallest global mv magnitude from the pred mv. 
					if(blkDiff == minDiff)
					{
            int currX = mx - predX0Rnd;
            int currY = my - predY0Rnd;
            int newX  = j - predX0Rnd;
            int newY  = i - predY0Rnd;
						int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
						if(vecDistDiff < 0)
							goto MEH264IF_FULL_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					mx = j;
					my = i;
				}//end if blkDiff...

				MEH264IF_FULL_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		///----------------------- Quarter pel refined search ----------------------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector (mx,my).
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IF_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IF_SubPos[x].x;
			int qOffY = 2 * MEH264IF_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IF_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
		int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IF_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IF_SubPos[x].x;
			int qOffY = hmy + MEH264IF_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IF_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		///----------------------- Quarter pel pred vector ----------------------------
    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 4) + predXQuart;
    predY = (predY0 * 4) + predYQuart;

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int predVecDiff = 0;
    /// Quarter read first if necessary.
    if(predXQuart || predYQuart)
    {
			/// Read the quarter grid pels into temp.
			_pExtRefOver->QuarterRead(*_pMBlkOver, predXQuart, predYQuart);
		/// Absolute/square diff comparison method.
#ifdef MEH264IF_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
#endif
    }//end if predXQuart...
    else
    {
#ifdef MEH264IF_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end else...

		/// Selection of the final motion vector is weighted with non-linear factors. The
    /// zero vector will be modified to the best of either the predicted mv or the zero mv.
    int zeromvx, zeromvy;
    if(predVecDiff <= zeroVecDiff)
    {
      zeroVecDiff = predVecDiff;
      zeromvx     = predX;
      zeromvy     = predY;
    }//end if predVecDiff...
    else
    {
      zeromvx     = 0;
      zeromvy     = 0;
    }//end else...

		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int weight						= 0;
		int magSqr						= (mvx * mvx) + (mvy * mvy);

#ifdef MEH264IF_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff * 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IF_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if(diffWithZeroDiff < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IF_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Decide whether or not to accept the final motion vector or revert to the zero/pred motion vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = zeromvx;
			mvy = zeromvy;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
      /// Set macroblock vector for future predictions.
      _pMVPred->Set16x16MotionVector(vecPos, mvx, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplFull::Destroy(void)
{
	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplFull::GetMotionRange( int  x,			int  y, 
																								  int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int boundary	= _extBoundary - MEH264IF_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplFull::GetMotionRange(	int  xpos,	int  ypos,
																									int	 xoff,	int  yoff,
																									int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	int boundary	= _extBoundary - MEH264IF_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;
	int	vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplFull::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IF_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IF_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IF_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...

    /// One further "h" and "G" col at the end of the row.
		/// "h"
		window[quartRow+2][quartCol] = MEH264IF_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];

	}//end fullRow...

   /// One further "b" and "G" row at the end.
	for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
	{
		/// "b"
		window[quartRow][quartCol+2] = MEH264IF_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];
	}//end for fullCol...

  /// ...and one final "G" full pel at the bottom right edge.
	window[quartRow][quartCol] = ref[refRow][refCol];

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplFull::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplFull::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.






========== END FILE: CodecUtils/MotionEstimatorH264ImplFull.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplFull.h ==========
Bundle entry: 90
Original bytes: 7348
Original SHA-256: 8b23c3649232ed14813b9d9b6bf435d8c6bed9ba098debaea3c58111ee40b191
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplFull

TAG						: MEH264IF

FILE NAME			: MotionEstimatorH264ImplFull.h

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLFULL_H
#define _MOTIONESTIMATORH264IMPLFULL_H

#include "IMotionEstimator.h"
#include "IMotionVectorPredictor.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IF_COORD
{
	short int x;
	short int y;
} MEH264IF_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplFull : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplFull(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred);

	MotionEstimatorH264ImplFull(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred,
																void*				            pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplFull(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
  virtual void	Reset(void)       {}
	virtual int		Ready(void)		    { return(_ready); }
  virtual void	SetMode(int mode) { _mode = mode; }
	virtual int		GetMode(void)     { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.

	/// Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.

	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;
  /// Attached motion vector predictor on construction.
  IMotionVectorPredictor* _pMVPred;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH264ImplFull.

#endif // !_MOTIONESTIMATORH264IMPLFULL_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplFull.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultires.cpp ==========
Bundle entry: 91
Original bytes: 49981
Original SHA-256: ba6a78cae1c4bd458ed90d0e213ad97a93321f6d161850bd53bea1e22bfa2399
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultires

TAG						: MEH264IM

FILE NAME			: MotionEstimatorH264ImplMultires.cpp

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplMultires.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IM_FULL_MOTION_NOISE_FLOOR					512
#define MEH264IM_MOTION_NOISE_FLOOR								 26 //24 //sqrt 512
#define MEH264IM_L0_MOTION_VECTOR_REFINED_RANGE		  2
#define MEH264IM_L1_MOTION_VECTOR_REFINED_RANGE		  2

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Different for different levels.
#define MEH264IM_PADDING													3	
#define MEH264IM_L1_PADDING												1	
#define MEH264IM_L2_PADDING												1	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IM_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IM_MOTION_SUB_POS_LENGTH 	8
MEH264IM_COORD MEH264IM_SubPos[MEH264IM_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH264IM_MOTION_BOTTOM_SUB_POS_LENGTH 5	///< Bottom edge search range.
MEH264IM_COORD MEH264IM_BottomSubPos[MEH264IM_MOTION_BOTTOM_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0}
};

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IM_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplMultires::MotionEstimatorH264ImplMultires(	const void* pSrc, 
																																	const void* pRef, 
																																	int					imgWidth, 
																																	int					imgHeight,
																																	int					motionRange)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;

}//end constructor.

MotionEstimatorH264ImplMultires::MotionEstimatorH264ImplMultires(	const void* pSrc, 
																														const void* pRef, 
																														int					imgWidth, 
																														int					imgHeight,
																														int					motionRange,
																														void*				pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplMultires::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Level 0: Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2.
	_pInL1						= NULL;			///< Input mem at (_l1Width * _l1Height).
	_l1Width					= 0;
	_l1Height					= 0;
	_l1MacroBlkWidth	= 0;
	_l1MacroBlkHeight = 0;
	_l1MotionRange		= 0;
	_pInL1Over				= NULL;			///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.
	_pInL2						= NULL;			///< Input mem at (_l2Width * _l2Height).
	_l2Width					= 0;
	_l2Height					= 0;
	_l2MacroBlkWidth	= 0;
	_l2MacroBlkHeight = 0;
	_l2MotionRange		= 0;
	_pInL2Over				= NULL;			///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.
	_pRefL1						= NULL;			///< Ref mem at (_l1Width * _l1Height).
	_pRefL1Over				= NULL; 		///< Ref overlay with whole level 1 block dim.
	_pExtRefL1				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL1Width				= 0;
	_extL1Height			= 0;
	_extL1Boundary		= 0;
	_pExtRefL1Over		= NULL;			///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.
	_pRefL2						= NULL;			///< Ref mem at (_l2Width * _l2Height).
	_pRefL2Over				= NULL; 		///< Ref overlay with whole level 2 block dim.
	_pExtRefL2				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL2Width				= 0;
	_extL2Height			= 0;
	_extL2Boundary		= 0;
	_pExtRefL2Over		= NULL;			///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH264ImplMultires::~MotionEstimatorH264ImplMultires(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplMultires::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Level 0: Put an overlay on the input with the block size set to the vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((short *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// Level 1 is Level 0 sub sampled by 2.
	_l1Width					= _imgWidth/2;
	_l1Height					= _imgHeight/2;
	_l1MacroBlkWidth	= _macroBlkWidth/2;
	_l1MacroBlkHeight = _macroBlkHeight/2;
	_l1MotionRange		= _motionRange/8;	///< _motionRange is in 1/4 pel units. Convert to full level 1 pel units.

	/// Level 1: Input mem at (_l1Width * _l1Height) must be alloc.
	_pInL1 = new short[_l1Width * _l1Height];

	/// Level 1: Input overlay with level 1 motion block dim.
	if(_pInL1 != NULL)
	{
		_pInL1Over = new OverlayMem2Dv2(_pInL1,_l1Width,_l1Height,_l1MacroBlkWidth,_l1MacroBlkHeight);
		if(_pInL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL1Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2 is Level 1 sub sampled by 2.
	_l2Width					= _l1Width/2;
	_l2Height					= _l1Height/2;
	_l2MacroBlkWidth	= _l1MacroBlkWidth/2;
	_l2MacroBlkHeight = _l1MacroBlkHeight/2;
	_l2MotionRange		= _l1MotionRange/2;

	/// Level 2: Input mem at (_l2Width * _l2Height) must be alloc.
	_pInL2 = new short[_l2Width * _l2Height];

	/// Level 2: Input overlay with level 2 motion block dim.
	if(_pInL2 != NULL)
	{
		_pInL2Over = new OverlayMem2Dv2(_pInL2,_l2Width,_l2Height,_l2MacroBlkWidth,_l2MacroBlkHeight);
		if(_pInL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL2Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// --------------- Configure ref overlays --------------------------------
	/// Level 0: Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore have its own mem.
	_pRefOver = new OverlayMem2Dv2((short *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock.
	_extBoundary = _macroBlkWidth + MEH264IM_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IM_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Level 0: Place an overlay on the extended boundary ref with block 
	/// size set to the motion vec dim..
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// Level 1: Ref mem at (_l1Width * _l1Height).
	_pRefL1 = new short[_l1Width * _l1Height];

	/// Level 1: Ref overlay with whole level 1 block dim.
	if(_pRefL1 != NULL)
	{
		_pRefL1Over = new OverlayMem2Dv2(_pRefL1, _l1Width, _l1Height, _l1Width, _l1Height);
		if(_pRefL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL1Over...
	}//end if _pRefL1...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 1: Extended ref mem _pExtRefL1 created by ExtendBoundary() call.
	_extL1Boundary = _l1MacroBlkWidth +  + MEH264IM_L1_PADDING;
	if(_l1MacroBlkHeight > _l1MacroBlkWidth)
		_extL1Boundary = _l1MacroBlkHeight +  + MEH264IM_L1_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL1, 
																				_l1Width,						
																				_l1Height, 
																				_extL1Boundary,
																				_extL1Boundary,
																				(void **)(&_pExtRefL1)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL1Width		= _l1Width + (2 * _extL1Boundary);
	_extL1Height	= _l1Height + (2 * _extL1Boundary);

	// Level 1: Ref overlay with level 1 motion block dim.
	_pExtRefL1Over = new OverlayExtMem2Dv2(	_pExtRefL1, 
																					_extL1Width,					///< new mem width.
																					_extL1Height,				///< new mem height.
																					_l1MacroBlkWidth,		///< block width.
																					_l1MacroBlkHeight,		///< block height.
																					_extL1Boundary,			///< boundary width.
																					_extL1Boundary);			///< boundary height.
	if(_pExtRefL1Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL1Over...

	/// Level 2: Ref mem at (_l2Width * _l2Height).
	_pRefL2 = new short[_l2Width * _l2Height];

	/// Level 2: Ref overlay with whole level 2 block dim.
	if(_pRefL2 != NULL)
	{
		_pRefL2Over = new OverlayMem2Dv2(_pRefL2, _l2Width, _l2Height, _l2Width, _l2Height);
		if(_pRefL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL2Over...
	}//end if _pRefL2...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2: Extended ref mem _pExtRefL2 created by ExtendBoundary() call.
	_extL2Boundary = _l2MacroBlkWidth +  + MEH264IM_L2_PADDING;
	if(_l2MacroBlkHeight > _l2MacroBlkWidth)
		_extL2Boundary = _l2MacroBlkHeight + MEH264IM_L2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL2, 
																				_l2Width,						
																				_l2Height, 
																				_extL2Boundary,
																				_extL2Boundary,
																				(void **)(&_pExtRefL2)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL2Width		= _l2Width + (2 * _extL2Boundary);
	_extL2Height	= _l2Height + (2 * _extL2Boundary);

	/// Level 2: Ref overlay with level 2 motion block dim.
	_pExtRefL2Over = new OverlayExtMem2Dv2(	_pExtRefL2, 
																					_extL2Width,				///< new mem width.
																					_extL2Height,				///< new mem height.
																					_l2MacroBlkWidth,		///< block width.
																					_l2MacroBlkHeight,	///< block height.
																					_extL2Boundary,			///< boundary width.
																					_extL2Boundary);		///< boundary height.
	if(_pExtRefL2Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL2Over...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half pel motion estimation and 
	/// compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= (6 + _macroBlkWidth) * 4;
	int winHeight = (6 + _macroBlkHeight) * 4;
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((short *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	_ready = 1;
	return(1);
}//end Create.

void	MotionEstimatorH264ImplMultires::Reset(void)
{
}//end Reset.

/** Set the speed mode.
This is a multresolution algorithm and the speed is increased by estimating
at lower levels but it is less accurate. Mode = 1 implies level 1 and mode = 2
for level 2. Mode = 0 is auto mode that selects an appropriate mode depending
on the resolution of the image. The selection is set to 2 if the image has
an area larger than 200x200.

@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void	MotionEstimatorH264ImplMultires::SetMode(int mode)
{
	if(mode == 0)	///< Auto mode.
	{
		int area = _imgWidth * _imgHeight;
		if(area > 40000)
			_mode = 2;
		else
			_mode = 1;
	}//end if mode...
	else
		_mode = mode;
}//end SetMode.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries and a
absolute difference criterion. The mode setting (_mode) determines
the level of resolution.
@param pSrc		: Input image to estimate.
@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void* MotionEstimatorH264ImplMultires::Estimate(long* avgDistortion)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH264IM_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 																///< Src width.
												_imgHeight, 															///< Src height.
												(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 																///< Src width.
													_l1Height, 																///< Src height.
													(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The [0,0] motion vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting point.

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute/square diff comparison method.
#ifdef MEH264IM_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far.

		///----------------------- Level 2 full pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Compiler directed distortion comparison method (absolute difference or square difference).
#ifdef MEH264IM_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif
			
    	/// Level 2: Search on a full pel grid over the defined L2 motion range.
			GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

    	for(i = yuRng; i <= ydRng; i++)
    	{
    	  for(j = xlRng; j <= xrRng; j++)
    	  {
                                        int blkDiff = 0;
					/// Early exit because zero motion vec already checked.
					if( !(i||j) )	goto MEH264IM_LEVEL2_BREAK;
			
					/// Set the block to the [j,i] motion vector around the [l,k] reference
					/// location.
					_pExtRefL2Over->SetOrigin(l+j, k+i);

#ifdef MEH264IM_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4LessThan(*_pExtRefL2Over, minDiffL2);
#else
//					int blkDiff = _pInL2Over->Tsd4x4PartialLessThan(*_pExtRefL2Over, minDiffL2);
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif
					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL2)
						{
							int vecDistDiff = ( (my*my)+(mx*mx) )-( (i*i)+(j*j) );
							if(vecDistDiff < 0)
								goto MEH264IM_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						mx = j;
						my = i;
					}//end if blkDiff...
			
					MEH264IM_LEVEL2_BREAK: ; ///< null.
    	  }//end for j...
    	}//end for i...

			mx = mx << 1; ///< Convert level 2 full pel units to level 1 full pel units ( x2 ).
			my = my << 1;
			
		}//end if _mode...

		///----------------------- Level 1 full pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);

		/// Absolute/square  diff comparison method.
#ifdef MEH264IM_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Level 1: Search on a full pel grid over the defined L1 motion range. The
		///					range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
				int blkDiff = 0;	
				/// Early exit because zero (centre) motion vec already checked.
				if( !(i||j) )	goto MEH264IM_LEVEL1_BREAK;

				/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference
				/// location.
				_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH264IM_ABS_DIFF
				blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
				blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//				int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif
				if(blkDiff <= minDiffL1)
				{
					/// Weight the equal diff with the smallest motion vector magnitude. 
					if(blkDiff == minDiffL1)
					{
						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
						if(vecDistDiff < 0)
							goto MEH264IM_LEVEL1_BREAK;
					}//end if blkDiff...

					minDiffL1 = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH264IM_LEVEL1_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		mx = (mx+rmx) * 2; ///< Convert level 1 full pel units to level 0 full pel units ( x2 ) after adding the L1 refinement.
		my = (my+rmy) * 2;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range. 

		/// Get the min diff at this location in level 0 grid units.
		_pExtRefOver->SetOrigin(n+mx,m+my);

#ifdef MEH264IM_ABS_DIFF
		minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH264IM_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
                                int blkDiff = 0; 
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IM_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH264IM_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
					blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
//				int blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global motion vector magnitude. 
					if(blkDiff == minDiff)
					{
						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
						if(vecDistDiff < 0)
							goto MEH264IM_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH264IM_LEVEL0_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		/// Add the refinement in full pixel units.
		mx += rmx;
		my += rmy;

		///----------------------- Level 0 quarter pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 
		/// refine to the .

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector [mx,my].
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IM_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IM_SubPos[x].x;
			int qOffY = 2 * MEH264IM_SubPos[x].y;

			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//		int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IM_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IM_SubPos[x].x;
			int qOffY = hmy + MEH264IM_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
//		int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only because minDiff will not hold the correct value.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		/// Validity of the motion vector is weighted with non-linear factors.
		int weight						= 0;
		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int magSqr						= (mvx * mvx) + (mvy * mvy);

#ifdef MEH264IM_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff * 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IM_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if(diffWithZeroDiff < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IM_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Decide whether or not to accept the final motion vector or revert to the zero vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = 0;
			mvy = 0;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplMultires::Destroy(void)
{
	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pInL1 != NULL)
		delete[] _pInL1;
	_pInL1 = NULL;

	if(_pInL1Over != NULL)
		delete _pInL1Over;
	_pInL1Over = NULL;

	if(_pInL2 != NULL)
		delete[] _pInL2;
	_pInL2 = NULL;

	if(_pInL2Over != NULL)
		delete _pInL2Over;
	_pInL2Over = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pRefL1 != NULL)
		delete[] _pRefL1;
	_pRefL1	= NULL;

	if(_pRefL1Over != NULL)
		delete _pRefL1Over;
	_pRefL1Over	= NULL;

	if(_pExtRefL1 != NULL)
		delete[] _pExtRefL1;
	_pExtRefL1 = NULL;

	if(_pExtRefL1Over != NULL)
		delete _pExtRefL1Over;
	_pExtRefL1Over = NULL;

	if(_pRefL2 != NULL)
		delete[] _pRefL2;
	_pRefL2	= NULL;

	if(_pRefL2Over != NULL)
		delete _pRefL2Over;
	_pRefL2Over	= NULL;

	if(_pExtRefL2 != NULL)
		delete[] _pExtRefL2;
	_pExtRefL2 = NULL;

	if(_pExtRefL2Over != NULL)
		delete _pExtRefL2Over;
	_pExtRefL2Over = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultires::GetMotionRange(	int  x,			int  y, 
																											int* xlr,		int* xrr, 
																											int* yur,		int* ydr,
																											int	 range,	int	 level)
{
	/// The level defines the members to use.
	int boundary, width, height;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IM_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IM_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IM_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			break;
	}//end switch level...

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultires::GetMotionRange(	int  xpos,	int  ypos,
																											int	 xoff,	int  yoff,
																											int* xlr,		int* xrr, 
																											int* yur,		int* ydr,
																											int	 range,	int	 level)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	/// The level defines the members to use.
	int boundary, width, height, vecRange;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IM_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			vecRange	= _l1MotionRange;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IM_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			vecRange	= _l2MotionRange;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IM_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.
			break;
	}//end switch level...

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplMultires::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IM_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IM_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IM_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...
	}//end fullRow...

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultires::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultires::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.




========== END FILE: CodecUtils/MotionEstimatorH264ImplMultires.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultires.h ==========
Bundle entry: 92
Original bytes: 8786
Original SHA-256: c3b9ad31f9055546e2a792780044c5771aef89f8e465ff90df6f9fabcdabdb3c
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultires

TAG						: MEH264IM

FILE NAME			: MotionEstimatorH264ImplMultires.h

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLMULTIRES_H
#define _MOTIONESTIMATORH264IMPLMULTIRES_H

#include "IMotionEstimator.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IM_COORD
{
	short int x;
	short int y;
} MEH264IM_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplMultires : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplMultires(	const void* pSrc, 
																		const void* pRef, 
																		int					imgWidth, 
																		int					imgHeight,
																		int					motionRange);

	MotionEstimatorH264ImplMultires(	const void* pSrc, 
																		const void* pRef, 
																		int					imgWidth, 
																		int					imgHeight,
																		int					motionRange,
																		void*				pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplMultires(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
	virtual void	Reset(void);
	virtual int		Ready(void)		{ return(_ready); }
	virtual void	SetMode(int mode);
	virtual int		GetMode(void) { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Level 0: Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2. [_mode == 1]
	short*						_pInL1;						///< Input mem at (_l1Width * _l1Height).
	int								_l1Width;
	int								_l1Height;
	int								_l1MacroBlkWidth;
	int								_l1MacroBlkHeight;
	int								_l1MotionRange;		///< Full pel level 1 units.
	OverlayMem2Dv2*		_pInL1Over;				///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.	[_mode == 2]
	short*						_pInL2;						///< Input mem at (_l2Width * _l2Height).
	int								_l2Width;
	int								_l2Height;
	int								_l2MacroBlkWidth;
	int								_l2MacroBlkHeight;
	int								_l2MotionRange;		///< Full pel level 2 units.
	OverlayMem2Dv2*		_pInL2Over;				///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.		[_mode == 1]
	short*							_pRefL1;					///< Ref mem at (_l1Width * _l1Height).
	OverlayMem2Dv2*			_pRefL1Over; 			///< Ref overlay with whole level 1 block dim.
	short*							_pExtRefL1;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL1Width;
	int									_extL1Height;
	int									_extL1Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL1Over;		///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.		[_mode == 2]
	short*							_pRefL2;					///< Ref mem at (_l2Width * _l2Height).
	OverlayMem2Dv2*			_pRefL2Over; 			///< Ref overlay with whole level 2 block dim.
	short*							_pExtRefL2;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL2Width;
	int									_extL2Height;
	int									_extL2Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL2Over;		///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH264ImplMultires.


#endif // !_MOTIONESTIMATORH264IMPLMULTIRES_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplMultires.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultiresCross.cpp ==========
Bundle entry: 93
Original bytes: 53047
Original SHA-256: 42fffb34eaf90a855bf0c953daa35fa2b8106493807d2c0b729f00f1cd617b88
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultiresCross

TAG						: MEH264IM

FILE NAME			: MotionEstimatorH264ImplMultiresCross.cpp

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range. The estimation is
								performed on lower resolution representations and at the 
								lowest resolution a cascaded cross search is performed.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplMultiresCross.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IMC_FULL_MOTION_NOISE_FLOOR					512
#define MEH264IMC_MOTION_NOISE_FLOOR							 26 //24 //sqrt 512
#define MEH264IMC_L0_MOTION_VECTOR_REFINED_RANGE		2
#define MEH264IMC_L1_MOTION_VECTOR_REFINED_RANGE		2

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Different for different levels.
#define MEH264IMC_PADDING													3	
#define MEH264IMC_L1_PADDING											1	
#define MEH264IMC_L2_PADDING											1	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IMC_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IMC_MOTION_SUB_POS_LENGTH 	8
MEH264IMC_COORD MEH264IMC_SubPos[MEH264IMC_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH264IMC_MOTION_CROSS_POS_LENGTH 	4
MEH264IMC_COORD MEH264IMC_CrossPos[MEH264IMC_MOTION_CROSS_POS_LENGTH]	= 
{
	{-1,0},{1,0},{0,-1},{0,1}
};

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IMC_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplMultiresCross::MotionEstimatorH264ImplMultiresCross(	const void* pSrc, 
																														const void* pRef, 
																														int					imgWidth, 
																														int					imgHeight,
																														int					motionRange)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;

}//end constructor.

MotionEstimatorH264ImplMultiresCross::MotionEstimatorH264ImplMultiresCross(	const void* pSrc, 
																														const void* pRef, 
																														int					imgWidth, 
																														int					imgHeight,
																														int					motionRange,
																														void*				pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplMultiresCross::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Level 0: Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2.
	_pInL1						= NULL;			///< Input mem at (_l1Width * _l1Height).
	_l1Width					= 0;
	_l1Height					= 0;
	_l1MacroBlkWidth	= 0;
	_l1MacroBlkHeight = 0;
	_l1MotionRange		= 0;
	_pInL1Over				= NULL;			///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.
	_pInL2						= NULL;			///< Input mem at (_l2Width * _l2Height).
	_l2Width					= 0;
	_l2Height					= 0;
	_l2MacroBlkWidth	= 0;
	_l2MacroBlkHeight = 0;
	_l2MotionRange		= 0;
	_pInL2Over				= NULL;			///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.
	_pRefL1						= NULL;			///< Ref mem at (_l1Width * _l1Height).
	_pRefL1Over				= NULL; 		///< Ref overlay with whole level 1 block dim.
	_pExtRefL1				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL1Width				= 0;
	_extL1Height			= 0;
	_extL1Boundary		= 0;
	_pExtRefL1Over		= NULL;			///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.
	_pRefL2						= NULL;			///< Ref mem at (_l2Width * _l2Height).
	_pRefL2Over				= NULL; 		///< Ref overlay with whole level 2 block dim.
	_pExtRefL2				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL2Width				= 0;
	_extL2Height			= 0;
	_extL2Boundary		= 0;
	_pExtRefL2Over		= NULL;			///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH264ImplMultiresCross::~MotionEstimatorH264ImplMultiresCross(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplMultiresCross::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Level 0: Put an overlay on the input with the block size set to the vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((short *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// Level 1 is Level 0 sub sampled by 2.
	_l1Width					= _imgWidth/2;
	_l1Height					= _imgHeight/2;
	_l1MacroBlkWidth	= _macroBlkWidth/2;
	_l1MacroBlkHeight = _macroBlkHeight/2;
	_l1MotionRange		= _motionRange/8;	///< _motionRange is in 1/4 pel units. Convert to full level 1 pel units.

	/// Level 1: Input mem at (_l1Width * _l1Height) must be alloc.
	_pInL1 = new short[_l1Width * _l1Height];

	/// Level 1: Input overlay with level 1 motion block dim.
	if(_pInL1 != NULL)
	{
		_pInL1Over = new OverlayMem2Dv2(_pInL1,_l1Width,_l1Height,_l1MacroBlkWidth,_l1MacroBlkHeight);
		if(_pInL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL1Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2 is Level 1 sub sampled by 2.
	_l2Width					= _l1Width/2;
	_l2Height					= _l1Height/2;
	_l2MacroBlkWidth	= _l1MacroBlkWidth/2;
	_l2MacroBlkHeight = _l1MacroBlkHeight/2;
	_l2MotionRange		= _l1MotionRange/2;

	/// Level 2: Input mem at (_l2Width * _l2Height) must be alloc.
	_pInL2 = new short[_l2Width * _l2Height];

	/// Level 2: Input overlay with level 2 motion block dim.
	if(_pInL2 != NULL)
	{
		_pInL2Over = new OverlayMem2Dv2(_pInL2,_l2Width,_l2Height,_l2MacroBlkWidth,_l2MacroBlkHeight);
		if(_pInL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL2Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// --------------- Configure ref overlays --------------------------------
	/// Level 0: Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore have its own mem.
	_pRefOver = new OverlayMem2Dv2((short *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock.
	_extBoundary = _macroBlkWidth + MEH264IMC_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IMC_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Level 0: Place an overlay on the extended boundary ref with block 
	/// size set to the motion vec dim..
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// Level 1: Ref mem at (_l1Width * _l1Height).
	_pRefL1 = new short[_l1Width * _l1Height];

	/// Level 1: Ref overlay with whole level 1 block dim.
	if(_pRefL1 != NULL)
	{
		_pRefL1Over = new OverlayMem2Dv2(_pRefL1, _l1Width, _l1Height, _l1Width, _l1Height);
		if(_pRefL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL1Over...
	}//end if _pRefL1...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 1: Extended ref mem _pExtRefL1 created by ExtendBoundary() call.
	_extL1Boundary = _l1MacroBlkWidth + MEH264IMC_L1_PADDING;
	if(_l1MacroBlkHeight > _l1MacroBlkWidth)
		_extL1Boundary = _l1MacroBlkHeight + MEH264IMC_L1_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL1, 
																				_l1Width,						
																				_l1Height, 
																				_extL1Boundary,
																				_extL1Boundary,
																				(void **)(&_pExtRefL1)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL1Width		= _l1Width + (2 * _extL1Boundary);
	_extL1Height	= _l1Height + (2 * _extL1Boundary);

	// Level 1: Ref overlay with level 1 motion block dim.
	_pExtRefL1Over = new OverlayExtMem2Dv2(	_pExtRefL1, 
																					_extL1Width,				///< new mem width.
																					_extL1Height,				///< new mem height.
																					_l1MacroBlkWidth,		///< block width.
																					_l1MacroBlkHeight,	///< block height.
																					_extL1Boundary,			///< boundary width.
																					_extL1Boundary);		///< boundary height.
	if(_pExtRefL1Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL1Over...

	/// Level 2: Ref mem at (_l2Width * _l2Height).
	_pRefL2 = new short[_l2Width * _l2Height];

	/// Level 2: Ref overlay with whole level 2 block dim.
	if(_pRefL2 != NULL)
	{
		_pRefL2Over = new OverlayMem2Dv2(_pRefL2, _l2Width, _l2Height, _l2Width, _l2Height);
		if(_pRefL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL2Over...
	}//end if _pRefL2...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2: Extended ref mem _pExtRefL2 created by ExtendBoundary() call.
	_extL2Boundary = _l2MacroBlkWidth + MEH264IMC_L2_PADDING;
	if(_l2MacroBlkHeight > _l2MacroBlkWidth)
		_extL2Boundary = _l2MacroBlkHeight + MEH264IMC_L2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL2, 
																				_l2Width,						
																				_l2Height, 
																				_extL2Boundary,
																				_extL2Boundary,
																				(void **)(&_pExtRefL2)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL2Width		= _l2Width + (2 * _extL2Boundary);
	_extL2Height	= _l2Height + (2 * _extL2Boundary);

	/// Level 2: Ref overlay with level 2 motion block dim.
	_pExtRefL2Over = new OverlayExtMem2Dv2(	_pExtRefL2, 
																					_extL2Width,				///< new mem width.
																					_extL2Height,				///< new mem height.
																					_l2MacroBlkWidth,		///< block width.
																					_l2MacroBlkHeight,	///< block height.
																					_extL2Boundary,			///< boundary width.
																					_extL2Boundary);		///< boundary height.
	if(_pExtRefL2Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL2Over...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half pel motion estimation and 
	/// compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= (6 + _macroBlkWidth) * 4;
	int winHeight = (6 + _macroBlkHeight) * 4;
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((short *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	_ready = 1;
	return(1);
}//end Create.

void	MotionEstimatorH264ImplMultiresCross::Reset(void)
{
}//end Reset.

/** Set the speed mode.
This is a multresolution algorithm and the speed is increased by estimating
at lower levels but it is less accurate. Mode = 1 implies level 1 and mode = 2
for level 2. Mode = 0 is auto mode that selects an appropriate mode depending
on the resolution of the image. The selection is set to 2 if the image has
an area larger than 200x200.

@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void	MotionEstimatorH264ImplMultiresCross::SetMode(int mode)
{
	if(mode == 0)	///< Auto mode.
	{
		int area = _imgWidth * _imgHeight;
		if(area > 40000)
			_mode = 2;
		else
			_mode = 1;
	}//end if mode...
	else
		_mode = mode;
}//end SetMode.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries and a
absolute difference criterion. The mode setting (_mode) determines
the level of resolution.
@param pSrc		: Input image to estimate.
@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void* MotionEstimatorH264ImplMultiresCross::Estimate(long* avgDistortion)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH264IMC_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 																///< Src width.
												_imgHeight, 															///< Src height.
												(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 																///< Src width.
													_l1Height, 																///< Src height.
													(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The [0,0] motion vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting point.

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute diff comparison method.
#ifdef MEH264IMC_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far.

		///----------------------- Level 2 full pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Compiler directed distortion comparison method (absolute difference or square difference).
#ifdef MEH264IMC_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif
			
    	/// Level 2: Search on a full pel grid over the defined L2 motion range.

			/// Cross search loop.
			for(int w = _l2MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMC_MOTION_CROSS_POS_LENGTH; x++)
				{
                                        int blkDiff = 0; 
					i = w * MEH264IMC_CrossPos[x].y;
					j = w * MEH264IMC_CrossPos[x].x;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMC_LEVEL2_BREAK;

					/// Set the block to the (j,i) offset motion vector from the (mx,my) motion vector
					/// around the (l,k) reference location.
					_pExtRefL2Over->SetOrigin(j+l+mx, i+k+my);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4LessThan(*_pExtRefL2Over, minDiffL2);
#else
//					blkDiff = _pInL2Over->Tsd4x4PartialLessThan(*_pExtRefL2Over, minDiffL2);
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif

					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL2)
						{
							int vecDistDiff = ( (my*my)+(mx*mx) )-( (i*i)+(j*j) );
							if(vecDistDiff < 0)
								goto MEH264IMC_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...
			
					MEH264IMC_LEVEL2_BREAK: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...
			
			mx = mx << 1; ///< Convert level 2 full pel units to level 1 full pel units ( x2 ).
			my = my << 1;
		}//end if _mode...

		///----------------------- Level 1 full pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);

		/// Absolute/square diff comparison method.
#ifdef MEH264IMC_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Level 1: Search on a cross pel grid over the defined L1 motion range if mode != 2. Otherwise
		///					 the range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;

		/// For mode = 2 (level 2 search has been done) do a refinement search.
		if(_mode == 2)
		{
			GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

			for(i = yuRng; i <= ydRng; i++)
			{
				for(j = xlRng; j <= xrRng; j++)
				{
                                        int blkDiff = 0; 
					/// Early exit because zero (centre) motion vec already checked.
					if( !(i||j) )	goto MEH264IMC_LEVEL1_BREAK;

					/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH264IMC_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH264IMC_LEVEL1_BREAK;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH264IMC_LEVEL1_BREAK: ; ///< null.
				}//end for j...
			}//end for i...
		}//end if mode == 2...
		else	///< Do a cross search.
		{
			/// For this case, this is the first entry point of the search i.e. (mx,my) = (0,0).

			for(int w = _l1MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange-1, 1);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMC_MOTION_CROSS_POS_LENGTH; x++)
				{
                                        int blkDiff = 0; 
					i = w * MEH264IMC_CrossPos[x].y;
					j = w * MEH264IMC_CrossPos[x].x;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMC_LEVEL1_BREAK_C;

					/// Set the block to the (j,i) motion vector around the (mx+p,my+q) reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					int blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif

					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH264IMC_LEVEL1_BREAK_C;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH264IMC_LEVEL1_BREAK_C: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

		}//end else...

		mx = (mx+rmx) * 2; ///< Convert level 1 full pel units to level 0 full pel units ( x2 ) after adding the L1 refinement.
		my = (my+rmy) * 2;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range.

		/// Get the min diff at this location in level 0 grid units.
		_pExtRefOver->SetOrigin(n+mx,m+my);

#ifdef MEH264IMC_ABS_DIFF
		minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH264IMC_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
                                int blkDiff = 0;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IMC_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH264IMC_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
//				blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global motion vector magnitude. 
					if(blkDiff == minDiff)
					{
						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
						if(vecDistDiff < 0)
							goto MEH264IMC_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH264IMC_LEVEL0_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		/// Add the refinement in full pixel units.
		mx += rmx;
		my += rmy;

		///----------------------- Level 0 quarter pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 
		/// refine to the .

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector [mx,my].
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IMC_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IMC_SubPos[x].x;
			int qOffY = 2 * MEH264IMC_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
		int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IMC_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IMC_SubPos[x].x;
			int qOffY = hmy + MEH264IMC_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMC_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		/// Validity of the motion vector is weighted with non-linear factors.
		int weight							= 0;
		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int magSqr							= (mvx * mvx) + (mvy * mvy);

#ifdef MEH264IMC_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff * 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IMC_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if(diffWithZeroDiff < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IMC_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Decide whether or not to accept the final motion vector or revert to the zero vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = 0;
			mvy = 0;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplMultiresCross::Destroy(void)
{
	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pInL1 != NULL)
		delete[] _pInL1;
	_pInL1 = NULL;

	if(_pInL1Over != NULL)
		delete _pInL1Over;
	_pInL1Over = NULL;

	if(_pInL2 != NULL)
		delete[] _pInL2;
	_pInL2 = NULL;

	if(_pInL2Over != NULL)
		delete _pInL2Over;
	_pInL2Over = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pRefL1 != NULL)
		delete[] _pRefL1;
	_pRefL1	= NULL;

	if(_pRefL1Over != NULL)
		delete _pRefL1Over;
	_pRefL1Over	= NULL;

	if(_pExtRefL1 != NULL)
		delete[] _pExtRefL1;
	_pExtRefL1 = NULL;

	if(_pExtRefL1Over != NULL)
		delete _pExtRefL1Over;
	_pExtRefL1Over = NULL;

	if(_pRefL2 != NULL)
		delete[] _pRefL2;
	_pRefL2	= NULL;

	if(_pRefL2Over != NULL)
		delete _pRefL2Over;
	_pRefL2Over	= NULL;

	if(_pExtRefL2 != NULL)
		delete[] _pExtRefL2;
	_pExtRefL2 = NULL;

	if(_pExtRefL2Over != NULL)
		delete _pExtRefL2Over;
	_pExtRefL2Over = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCross::GetMotionRange(int  x,			int  y, 
																													int* xlr,		int* xrr, 
																													int* yur,		int* ydr,
																													int	 range,	int	 level)
{
	/// The level defines the members to use.
	int boundary, width, height;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IMC_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IMC_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IMC_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			break;
	}//end switch level...

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCross::GetMotionRange(	int  xpos,	int  ypos,
																														int	 xoff,	int  yoff,
																														int* xlr,		int* xrr, 
																														int* yur,		int* ydr,
																														int	 range,	int	 level)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	/// The level defines the members to use.
	int boundary, width, height, vecRange;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IMC_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			vecRange	= _l1MotionRange;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IMC_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			vecRange	= _l2MotionRange;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IMC_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.
			break;
	}//end switch level...

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCross::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IMC_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IMC_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IMC_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...
	}//end fullRow...

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultiresCross::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultiresCross::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.




========== END FILE: CodecUtils/MotionEstimatorH264ImplMultiresCross.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultiresCross.h ==========
Bundle entry: 94
Original bytes: 8989
Original SHA-256: 7789a520c47991168e6423cb682e1cbdb6f553a0bc4ce88431165158edf8ac61
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultiresCross

TAG						: MEH264IMC

FILE NAME			: MotionEstimatorH264ImplMultiresCross.h

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range. The estimation is
								performed on lower resolution representations and at the 
								lowest resolution a cascaded cross search is performed.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLMULTIRESCROSS_H
#define _MOTIONESTIMATORH264IMPLMULTIRESCROSS_H

#include "IMotionEstimator.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IMC_COORD
{
	short int x;
	short int y;
} MEH264IMC_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplMultiresCross : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplMultiresCross(	const void* pSrc, 
																		const void* pRef, 
																		int					imgWidth, 
																		int					imgHeight,
																		int					motionRange);

	MotionEstimatorH264ImplMultiresCross(	const void* pSrc, 
																		const void* pRef, 
																		int					imgWidth, 
																		int					imgHeight,
																		int					motionRange,
																		void*				pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplMultiresCross(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
	virtual void	Reset(void);
	virtual int		Ready(void)		{ return(_ready); }
	virtual void	SetMode(int mode);
	virtual int		GetMode(void) { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Level 0: Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2. [_mode == 1]
	short*						_pInL1;						///< Input mem at (_l1Width * _l1Height).
	int								_l1Width;
	int								_l1Height;
	int								_l1MacroBlkWidth;
	int								_l1MacroBlkHeight;
	int								_l1MotionRange;		///< Full pel level 1 units.
	OverlayMem2Dv2*		_pInL1Over;				///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.	[_mode == 2]
	short*						_pInL2;						///< Input mem at (_l2Width * _l2Height).
	int								_l2Width;
	int								_l2Height;
	int								_l2MacroBlkWidth;
	int								_l2MacroBlkHeight;
	int								_l2MotionRange;		///< Full pel level 2 units.
	OverlayMem2Dv2*		_pInL2Over;				///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.		[_mode == 1]
	short*							_pRefL1;					///< Ref mem at (_l1Width * _l1Height).
	OverlayMem2Dv2*			_pRefL1Over; 			///< Ref overlay with whole level 1 block dim.
	short*							_pExtRefL1;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL1Width;
	int									_extL1Height;
	int									_extL1Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL1Over;		///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.		[_mode == 2]
	short*							_pRefL2;					///< Ref mem at (_l2Width * _l2Height).
	OverlayMem2Dv2*			_pRefL2Over; 			///< Ref overlay with whole level 2 block dim.
	short*							_pExtRefL2;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL2Width;
	int									_extL2Height;
	int									_extL2Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL2Over;		///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH264ImplMultiresCross.


#endif // !_MOTIONESTIMATORH264IMPLMULTIRESCROSS_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplMultiresCross.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.cpp ==========
Bundle entry: 95
Original bytes: 83114
Original SHA-256: 8416d8cf5e5d8c83e4f727f538363151c07a3bb05164d6366ee689ecd90fafdd
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultiresCrossVer2

TAG						: MEH264IMV2

FILE NAME			: MotionEstimatorH264ImplMultiresCrossVer2.cpp

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range. The estimation is
								performed on lower resolution representations and at the 
								lowest resolution a cascaded cross search is performed.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplMultiresCrossVer2.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IMCV2_FULL_MOTION_NOISE_FLOOR					512
#define MEH264IMCV2_MOTION_NOISE_FLOOR							 26 //24 //sqrt 512
#define MEH264IMCV2_L0_MOTION_VECTOR_REFINED_RANGE		2
#define MEH264IMCV2_L1_MOTION_VECTOR_REFINED_RANGE		2

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. Different for different levels.
#define MEH264IMCV2_PADDING													3	
#define MEH264IMCV2_L1_PADDING											1	
#define MEH264IMCV2_L2_PADDING											1	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IMCV2_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IMCV2_MOTION_SUB_POS_LENGTH 	8
MEH264IMCV2_COORD MEH264IMCV2_SubPos[MEH264IMCV2_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

#define MEH264IMCV2_MOTION_CROSS_POS_LENGTH 	4
MEH264IMCV2_COORD MEH264IMCV2_CrossPos[MEH264IMCV2_MOTION_CROSS_POS_LENGTH]	= 
{
	{-1,0},{1,0},{0,-1},{0,1}
};

/// Num of items in the Fifos.
#define MEH264IMCV2_FIFO_LENGTH 5

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IMCV2_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplMultiresCrossVer2::MotionEstimatorH264ImplMultiresCrossVer2(	const void*             pSrc, 
																														                        const void*             pRef, 
																														                        int					            imgWidth, 
																														                        int					            imgHeight,
																														                        int					            motionRange,
                                                                                    IMotionVectorPredictor* pMVPred)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;
  _pMVPred        = pMVPred;

}//end constructor.

MotionEstimatorH264ImplMultiresCrossVer2::MotionEstimatorH264ImplMultiresCrossVer2(	const void*             pSrc, 
																														                        const void*             pRef, 
																														                        int					            imgWidth, 
																														                        int					            imgHeight,
																														                        int					            motionRange,
                                                                                    IMotionVectorPredictor* pMVPred,
																														                        void*				            pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
  _pMVPred              = pMVPred;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplMultiresCrossVer2::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Level 0: Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2.
	_pInL1						= NULL;			///< Input mem at (_l1Width * _l1Height).
	_l1Width					= 0;
	_l1Height					= 0;
	_l1MacroBlkWidth	= 0;
	_l1MacroBlkHeight = 0;
	_l1MotionRange		= 0;
	_pInL1Over				= NULL;			///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.
	_pInL2						= NULL;			///< Input mem at (_l2Width * _l2Height).
	_l2Width					= 0;
	_l2Height					= 0;
	_l2MacroBlkWidth	= 0;
	_l2MacroBlkHeight = 0;
	_l2MotionRange		= 0;
	_pInL2Over				= NULL;			///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.
	_pRefL1						= NULL;			///< Ref mem at (_l1Width * _l1Height).
	_pRefL1Over				= NULL; 		///< Ref overlay with whole level 1 block dim.
	_pExtRefL1				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL1Width				= 0;
	_extL1Height			= 0;
	_extL1Boundary		= 0;
	_pExtRefL1Over		= NULL;			///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.
	_pRefL2						= NULL;			///< Ref mem at (_l2Width * _l2Height).
	_pRefL2Over				= NULL; 		///< Ref overlay with whole level 2 block dim.
	_pExtRefL2				= NULL;			///< Extended ref mem create by ExtendBoundary() call.
	_extL2Width				= 0;
	_extL2Height			= 0;
	_extL2Boundary		= 0;
	_pExtRefL2Over		= NULL;			///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;
  /// Attached motion vector predictor on construction.
  _pMVPred             = NULL;

  /// Set up the fifos.
  _xVector.Create(MEH264IMCV2_FIFO_LENGTH);
  _yVector.Create(MEH264IMCV2_FIFO_LENGTH);
  _distVector.Create(MEH264IMCV2_FIFO_LENGTH);

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;
}//end ResetMembers.

MotionEstimatorH264ImplMultiresCrossVer2::~MotionEstimatorH264ImplMultiresCrossVer2(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplMultiresCrossVer2::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Level 0: Put an overlay on the input with the block size set to the vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((short *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// Level 1 is Level 0 sub sampled by 2.
	_l1Width					= _imgWidth/2;
	_l1Height					= _imgHeight/2;
	_l1MacroBlkWidth	= _macroBlkWidth/2;
	_l1MacroBlkHeight = _macroBlkHeight/2;
	_l1MotionRange		= _motionRange/8;	///< _motionRange is in 1/4 pel units. Convert to full level 1 pel units.

	/// Level 1: Input mem at (_l1Width * _l1Height) must be alloc.
	_pInL1 = new short[_l1Width * _l1Height];

	/// Level 1: Input overlay with level 1 motion block dim.
	if(_pInL1 != NULL)
	{
		_pInL1Over = new OverlayMem2Dv2(_pInL1,_l1Width,_l1Height,_l1MacroBlkWidth,_l1MacroBlkHeight);
		if(_pInL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL1Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2 is Level 1 sub sampled by 2.
	_l2Width					= _l1Width/2;
	_l2Height					= _l1Height/2;
	_l2MacroBlkWidth	= _l1MacroBlkWidth/2;
	_l2MacroBlkHeight = _l1MacroBlkHeight/2;
	_l2MotionRange		= _l1MotionRange/2;

	/// Level 2: Input mem at (_l2Width * _l2Height) must be alloc.
	_pInL2 = new short[_l2Width * _l2Height];

	/// Level 2: Input overlay with level 2 motion block dim.
	if(_pInL2 != NULL)
	{
		_pInL2Over = new OverlayMem2Dv2(_pInL2,_l2Width,_l2Height,_l2MacroBlkWidth,_l2MacroBlkHeight);
		if(_pInL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if !_pInL2Over...
	}//end if ...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// --------------- Configure ref overlays --------------------------------
	/// Level 0: Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore have its own mem.
	_pRefOver = new OverlayMem2Dv2((short *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock.
	_extBoundary = _macroBlkWidth + MEH264IMCV2_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IMCV2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Level 0: Place an overlay on the extended boundary ref with block 
	/// size set to the motion vec dim..
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// Level 1: Ref mem at (_l1Width * _l1Height).
	_pRefL1 = new short[_l1Width * _l1Height];

	/// Level 1: Ref overlay with whole level 1 block dim.
	if(_pRefL1 != NULL)
	{
		_pRefL1Over = new OverlayMem2Dv2(_pRefL1, _l1Width, _l1Height, _l1Width, _l1Height);
		if(_pRefL1Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL1Over...
	}//end if _pRefL1...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 1: Extended ref mem _pExtRefL1 created by ExtendBoundary() call.
	_extL1Boundary = _l1MacroBlkWidth + MEH264IMCV2_L1_PADDING;
	if(_l1MacroBlkHeight > _l1MacroBlkWidth)
		_extL1Boundary = _l1MacroBlkHeight + MEH264IMCV2_L1_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL1, 
																				_l1Width,						
																				_l1Height, 
																				_extL1Boundary,
																				_extL1Boundary,
																				(void **)(&_pExtRefL1)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL1Width		= _l1Width + (2 * _extL1Boundary);
	_extL1Height	= _l1Height + (2 * _extL1Boundary);

	// Level 1: Ref overlay with level 1 motion block dim.
	_pExtRefL1Over = new OverlayExtMem2Dv2(	_pExtRefL1, 
																					_extL1Width,				///< new mem width.
																					_extL1Height,				///< new mem height.
																					_l1MacroBlkWidth,		///< block width.
																					_l1MacroBlkHeight,	///< block height.
																					_extL1Boundary,			///< boundary width.
																					_extL1Boundary);		///< boundary height.
	if(_pExtRefL1Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL1Over...

	/// Level 2: Ref mem at (_l2Width * _l2Height).
	_pRefL2 = new short[_l2Width * _l2Height];

	/// Level 2: Ref overlay with whole level 2 block dim.
	if(_pRefL2 != NULL)
	{
		_pRefL2Over = new OverlayMem2Dv2(_pRefL2, _l2Width, _l2Height, _l2Width, _l2Height);
		if(_pRefL2Over == NULL)
		{
			Destroy();
			return(0);
		}//end if _pRefL2Over...
	}//end if _pRefL2...
	else
	{
		Destroy();
		return(0);
	}//end else...

	/// Level 2: Extended ref mem _pExtRefL2 created by ExtendBoundary() call.
	_extL2Boundary = _l2MacroBlkWidth + MEH264IMCV2_L2_PADDING;
	if(_l2MacroBlkHeight > _l2MacroBlkWidth)
		_extL2Boundary = _l2MacroBlkHeight + MEH264IMCV2_L2_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRefL2, 
																				_l2Width,						
																				_l2Height, 
																				_extL2Boundary,
																				_extL2Boundary,
																				(void **)(&_pExtRefL2)) )
  {
    Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extL2Width		= _l2Width + (2 * _extL2Boundary);
	_extL2Height	= _l2Height + (2 * _extL2Boundary);

	/// Level 2: Ref overlay with level 2 motion block dim.
	_pExtRefL2Over = new OverlayExtMem2Dv2(	_pExtRefL2, 
																					_extL2Width,				///< new mem width.
																					_extL2Height,				///< new mem height.
																					_l2MacroBlkWidth,		///< block width.
																					_l2MacroBlkHeight,	///< block height.
																					_extL2Boundary,			///< boundary width.
																					_extL2Boundary);		///< boundary height.
	if(_pExtRefL2Over == NULL)
  {
    Destroy();
	  return(0);
  }//end if !_pExtRefL2Over...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half pel motion estimation and 
	/// compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= ((6 + _macroBlkWidth) * 4);
	int winHeight = ((6 + _macroBlkHeight) * 4);
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((short *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	_ready = 1;
	return(1);
}//end Create.

void	MotionEstimatorH264ImplMultiresCrossVer2::Reset(void)
{
}//end Reset.

/** Set the speed mode.
This is a multresolution algorithm and the speed is increased by estimating
at lower levels but it is less accurate. Mode = 1 implies level 1 and mode = 2
for level 2. Mode = 0 is auto mode that selects an appropriate mode depending
on the resolution of the image. The selection is set to 2 if the image has
an area larger than 200x200.

@param pRef		: Ref to estimate with.
@return				: The list of motion vectors.
*/
void	MotionEstimatorH264ImplMultiresCrossVer2::SetMode(int mode)
{
	if(mode == 0)	///< Auto mode.
	{
		int area = _imgWidth * _imgHeight;
		if(area > 40000)
			_mode = 2;
		else
			_mode = 1;
	}//end if mode...
	else
		_mode = mode;
}//end SetMode.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries. The 
mode setting (_mode) determines the level of resolution.
@param avgDistortion  : Return the average distortion of the estimation.
@return				        : The list of motion vectors.
*/
void* MotionEstimatorH264ImplMultiresCrossVer2::Estimate(long* avgDistortion)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH264IMCV2_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 																///< Src width.
												_imgHeight, 															///< Src height.
												(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 																///< Src width.
													_l1Height, 																///< Src height.
													(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.

    int predX, predY, predX0Rnd, predY0Rnd, predX1, predY1, predX2, predY2;
    _pMVPred->Get16x16Prediction(NULL, vecPos, &predX, &predY);
    int predXQuart  = predX % 4;
    int predYQuart  = predY % 4;
    int predX0      = predX / 4;
    int predY0      = predY / 4;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 2)/4;
    else
      predX0Rnd = (predX + 2)/4;
    if(predY < 0)
      predY0Rnd = (predY - 2)/4;
    else
      predY0Rnd = (predY + 2)/4;
    predX1   = predX0Rnd / 2; ///< Nearest level 1 pred motion vector.
    predY1   = predY0Rnd / 2;
    predX2   = predX1 / 2;    ///< Nearest level 2 pred motion vector.
    predY2   = predY1 / 2;

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute diff comparison method.
#ifdef MEH264IMCV2_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far at level 0.

		///----------------------- Level 2 full pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Compiler directed distortion comparison method (absolute difference or square difference).
#ifdef MEH264IMCV2_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif
			
    	/// Level 2: Search on a full pel grid over the defined L2 motion range.

			/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
			GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

			/// Cross search loop.
			for(int w = _l2MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
					i = w * MEH264IMCV2_CrossPos[x].y;
					j = w * MEH264IMCV2_CrossPos[x].x;
					int blkDiff;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMCV2_LEVEL2_BREAK;

					/// Set the block to the (j,i) offset motion vector from the (mx,my) motion vector
					/// around the (l,k) reference location.
					_pExtRefL2Over->SetOrigin(j+l+mx, i+k+my);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4LessThan(*_pExtRefL2Over, minDiffL2);
#else
//					blkDiff = _pInL2Over->Tsd4x4PartialLessThan(*_pExtRefL2Over, minDiffL2);
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif

					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest mv magnitude from the 
            /// predicted mv. 
						if(blkDiff == minDiffL2)
						{
//							int vecDistDiff = ( (my*my)+(mx*mx) )-( (i*i)+(j*j) );
              int currX = mx + rmx - predX2;
              int currY = my + rmy - predY2;
              int newX  = mx + j - predX2;
              int newY  = my + i - predY2;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
							if(vecDistDiff < 0)
								goto MEH264IMCV2_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...
			
					MEH264IMCV2_LEVEL2_BREAK: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...
			
			mx = mx << 1; ///< Convert level 2 full pel units to level 1 full pel units ( x2 ).
			my = my << 1;
		}//end if _mode...

		///----------------------- Level 1 full pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);

		/// Absolute/square diff comparison method.
#ifdef MEH264IMCV2_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Level 1: Search on a cross pel grid over the defined L1 motion range if mode != 2. Otherwise
		///					 the range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;

		/// For mode = 2 (level 2 search has been done) do a refinement search.
		if(_mode == 2)
		{
			GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

			for(i = yuRng; i <= ydRng; i++)
			{
				for(j = xlRng; j <= xrRng; j++)
				{
					int blkDiff;
					/// Early exit because zero (centre) motion vec already checked.
					if( !(i||j) )	goto MEH264IMCV2_LEVEL1_BREAK;

					/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH264IMCV2_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest mv magnitude from the predicted mv. 
						if(blkDiff == minDiffL1)
						{
              int currX = mx + rmx - predX1;
              int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;
              int newY  = my + i - predY1;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
//							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
							if(vecDistDiff < 0)
								goto MEH264IMCV2_LEVEL1_BREAK;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH264IMCV2_LEVEL1_BREAK: ; ///< null.
				}//end for j...
			}//end for i...
		}//end if mode == 2...
		else	///< Do a cross search.
		{
			/// For this case, this is the first entry point of the search i.e. (mx,my) = (0,0).

			for(int w = _l1MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange-1, 1);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
					i = w * MEH264IMCV2_CrossPos[x].y;
					j = w * MEH264IMCV2_CrossPos[x].x;
					int blkDiff;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMCV2_LEVEL1_BREAK_C;

					/// Set the block to the (j,i) motion vector around the (mx+p,my+q) reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
//					blkDiff = _pInL1Over->Tsd8x8LessThan(*_pExtRefL1Over, minDiffL1);
#endif

					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
//							int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
              int currX = mx + rmx - predX1;
              int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;
              int newY  = my + i - predY1;
							int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
							if(vecDistDiff < 0)
								goto MEH264IMCV2_LEVEL1_BREAK_C;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j;
						rmy = i;
					}//end if blkDiff...

					MEH264IMCV2_LEVEL1_BREAK_C: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

		}//end else...

		mx = (mx+rmx) * 2; ///< Convert level 1 full pel units to level 0 full pel units ( x2 ) after adding the L1 refinement.
		my = (my+rmy) * 2;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range.

		/// Get the min diff at this location in level 0 grid units only if (mx,my) is not the zero mv because minDiff
    /// was initialised to zeroVecDiff at the start.
		_pExtRefOver->SetOrigin(n+mx,m+my);

    if(mx||my)
    {
#ifdef MEH264IMCV2_ABS_DIFF
		  minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end if mx...

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH264IMCV2_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
				int blkDiff;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IMCV2_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH264IMCV2_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
//				blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global mv magnitude from the pred mv. 
					if(blkDiff == minDiff)
					{
//						int vecDistDiff = ( ((my+rmy)*(my+rmy))+((mx+rmx)*(mx+rmx)) )-( ((my+i)*(my+i))+((mx+j)*(mx+j)) );
            int currX = mx + rmx - predX0Rnd;
            int currY = my + rmy - predY0Rnd;
            int newX  = mx + j - predX0Rnd;
            int newY  = my + i - predY0Rnd;
						int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
						if(vecDistDiff < 0)
							goto MEH264IMCV2_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j;
					rmy = i;
				}//end if blkDiff...

				MEH264IMCV2_LEVEL0_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		/// Add the refinement in full pixel units.
		mx += rmx;
		my += rmy;

		///----------------------- Level 0 quarter pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector (mx,my).
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IMCV2_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IMCV2_SubPos[x].x;
			int qOffY = 2 * MEH264IMCV2_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
		int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IMCV2_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IMCV2_SubPos[x].x;
			int qOffY = hmy + MEH264IMCV2_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		///----------------------- Level 0 quarter pel pred vector ------------------------
    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 4) + predXQuart;
    predY = (predY0 * 4) + predYQuart;

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int predVecDiff = 0;
    /// Quarter read first if necessary.
    if(predXQuart || predYQuart)
    {
			/// Read the quarter grid pels into temp.
			_pExtRefOver->QuarterRead(*_pMBlkOver, predXQuart, predYQuart);
		/// Absolute/square diff comparison method.
#ifdef MEH264IMCV2_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
#endif
    }//end if predXQuart...
    else
    {
#ifdef MEH264IMCV2_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end else...

    /// Initialise the fifos and load the zero vector, pred vector and the curr best vector.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn(0.0); _yVector.AddFirstIn(0.0); _distVector.AddFirstIn((double)zeroVecDiff);
    _xVector.AddFirstIn((double)predX); _yVector.AddFirstIn((double)predY); _distVector.AddFirstIn((double)predVecDiff);
    _xVector.AddFirstIn((double)mvx); _yVector.AddFirstIn((double)mvy); _distVector.AddFirstIn((double)minDiff);
    /// Make a Legrange multiplier based selection for a more optimal motion vector.
    int vpos = GetBestVector(&_distVector, &_xVector, &_yVector, 0.9, 256.0, 2, predX, predY, &mvx, &mvy);

		/// Check for inclusion in the distortion calculation.
		if(_pDistortionIncluded != NULL)
    {
      mvx = (int)_xVector.GetItem(vpos);
      mvy = (int)_yVector.GetItem(vpos);
			if(_pDistortionIncluded[vecPos])
      {
			  included++;
        totalDifference += (int)_distVector.GetItem(vpos);
      }//end if _pDistortionIncluded...
    }//end if _pDistortionIncluded...

/// Old code below is retained for comparison purposes.
/*
		/// Selection of the final motion vector is weighted with non-linear factors. The
    /// zero vector will be modified to the best of either the predicted mv or the zero mv.
    int zeromvx, zeromvy;
    if(predVecDiff <= zeroVecDiff)
    {
      zeroVecDiff = predVecDiff;
      zeromvx     = predX;
      zeromvy     = predY;
    }//end if predVecDiff...
    else
    {
      zeromvx     = 0;
      zeromvy     = 0;
    }//end else...

		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int weight						= 0;
		int magSqr						= (mvx * mvx) + (mvy * mvy);

#ifdef MEH264IMCV2_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff * 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IMCV2_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if(diffWithZeroDiff < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IMCV2_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Decide whether or not to accept the final motion vector or revert to the zero/pred motion vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = zeromvx;
			mvy = zeromvy;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...
*/
		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
      /// Set macroblock vector for future predictions.
      _pMVPred->Set16x16MotionVector(vecPos, mvx, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a multiresolution search algorithm with extended boundaries. The 
mode setting (_mode) determines the level of resolution.
@param avgDistortion  : Return the average distortion of the estimation.
@param param          : An implementation specific parameter.
@return				        : The list of motion vectors.
*/
void* MotionEstimatorH264ImplMultiresCrossVer2::Estimate(long* avgDistortion, void* param)
{
  int		i,j,m,n,p,q,k,l;
	int		included = 0;
	long	totalDifference = 0;
  /// The param is defined as the cost function Le Grange multiplied in this implementation.
  double lambda = *((double *)(param));

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

  /// Store ordered results in fifo and clear.
  _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();

	/// Level 1 motion range is adjusted to a refinement if level 2 (_mode = 2)
	/// is to be used.
	int lclL1MotionRange = _l1MotionRange;
	if(_mode == 2)
		lclL1MotionRange = MEH264IMCV2_L1_MOTION_VECTOR_REFINED_RANGE;

	/// Write the level 0 ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Subsample level 0 ref (_pRefOver) to produce level 1 ref (_pRefL1Over).
	OverlayMem2Dv2::Half( (void **)(_pRefOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 																///< Src width.
												_imgHeight, 															///< Src height.
												(void **)(_pRefL1Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
	/// Write the level 1 extended ref and fill its boundary.
	_pExtRefL1Over->SetOrigin(0, 0);
	_pExtRefL1Over->SetOverlayDim(_l1Width, _l1Height);
	_pExtRefL1Over->Write(*_pRefL1Over);		///< _pRefL1Over is always set to the whole image.
	_pExtRefL1Over->FillBoundaryProxy();
	_pExtRefL1Over->SetOverlayDim(_l1MacroBlkWidth, _l1MacroBlkHeight);

	if(_mode == 2)
	{
		/// Subsample level 1 ref (_pRefL1Over) to produce level 2 ref (_pRefL2Over).
		OverlayMem2Dv2::Half( (void **)(_pRefL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 																///< Src width.
													_l1Height, 																///< Src height.
													(void **)(_pRefL2Over->Get2DSrcPtr()) );	///< Dest 2D ptr.
		/// Write the level 2 extended ref and fill its boundary.
		_pExtRefL2Over->SetOrigin(0, 0);
		_pExtRefL2Over->SetOverlayDim(_l2Width, _l2Height);
		_pExtRefL2Over->Write(*_pRefL2Over);	///< _pRefL2Over is always set to the whole image.
		_pExtRefL2Over->FillBoundaryProxy();
		_pExtRefL2Over->SetOverlayDim(_l2MacroBlkWidth, _l2MacroBlkHeight);
	}//end if _mode...

	/// Subsample level 0 input (_pInOver) to produce level 1 input (_pInL1Over).
	OverlayMem2Dv2::Half( (void **)(_pInOver->Get2DSrcPtr()),			///< Src 2D ptr.
												_imgWidth, 															///< Src width.
												_imgHeight, 														///< Src height.
												(void **)(_pInL1Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.

	if(_mode == 2)
	{
		/// Subsample level 1 input (_pInL1Over) to produce level 2 input (_pInL2Over).
		OverlayMem2Dv2::Half( (void **)(_pInL1Over->Get2DSrcPtr()),		///< Src 2D ptr.
													_l1Width, 															///< Src width.
													_l1Height, 															///< Src height.
													(void **)(_pInL2Over->Get2DSrcPtr()) ); ///< Dest 2D ptr.
	}//end if _mode...

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
	/// p,q step level 1 vec dim = _l1MacroBlkHeight, _l1MacroBlkWidth.
	/// k,l step level 2 vec dim = _l2MacroBlkHeight, _l2MacroBlkWidth.
  for(m = 0, p = 0, k = 0; m < _imgHeight; m += _macroBlkHeight, p += _l1MacroBlkHeight, k += _l2MacroBlkHeight)
		for(n = 0, q = 0, l = 0; n < _imgWidth; n += _macroBlkWidth, q += _l1MacroBlkWidth, l += _l2MacroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.

    int predX, predY, predX0Rnd, predY0Rnd, predX1, predY1, predX2, predY2;
    _pMVPred->Get16x16Prediction(NULL, vecPos, &predX, &predY);
    int predXQuart  = predX % 4;
    int predYQuart  = predY % 4;
    int predX0      = predX / 4;
    int predY0      = predY / 4;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 2)/4;
    else
      predX0Rnd = (predX + 2)/4;
    if(predY < 0)
      predY0Rnd = (predY - 2)/4;
    else
      predY0Rnd = (predY + 2)/4;
    predX1   = predX0Rnd / 2; ///< Nearest level 1 pred motion vector.
    predY1   = predY0Rnd / 2;
    predX2   = predX1 / 2;    ///< Nearest level 2 pred motion vector.
    predY2   = predY1 / 2;

		/// Level 0: Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// Absolute or square diff comparison method selection.
#ifdef MEH264IMCV2_ABS_DIFF
		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
		int minDiff			= zeroVecDiff;	///< Best so far at level 0.

		///----------------------- Level 2 full pel search --------------------------------
		if(_mode == 2)
		{
			/// Level 2: Set the input and ref blocks.
			_pInL2Over->SetOrigin(l,k);
			_pExtRefL2Over->SetOrigin(l,k);

			/// Compiler directed distortion comparison method (absolute difference or square difference) for
      /// the level 2 zero vector.
#ifdef MEH264IMCV2_ABS_DIFF
			int minDiffL2 = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
			int minDiffL2 = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
#endif

      /// Initialise the fifos with the zero vector.
      _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
      _xVector.AddFirstIn(0.0); _yVector.AddFirstIn(0.0); _distVector.AddFirstIn((double)minDiffL2);

    	/// Level 2: Search on a full pel grid over the defined L2 motion range.

			/// The centre is readjusted on every loop therefore the ranges must be recalculated.
			GetMotionRange(l, k, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _l2MotionRange-1, 2);

			/// Cross search loop.
			for(int w = _l2MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
					i = w * MEH264IMCV2_CrossPos[x].y;
					j = w * MEH264IMCV2_CrossPos[x].x;
					int blkDiff;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMCV2_LEVEL2_BREAK;

					/// Set the block to the (j,i) offset motion vector from the (mx,my) motion vector
					/// around the (l,k) reference location.
					_pExtRefL2Over->SetOrigin(j+l+mx, i+k+my);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL2Over->Tad4x4(*_pExtRefL2Over);
#else
//					blkDiff = _pInL2Over->Tsd4x4(*_pExtRefL2Over);
					blkDiff = _pInL2Over->Tsd4x4LessThan(*_pExtRefL2Over, minDiffL2);
#endif
					if(blkDiff <= minDiffL2)
					{
						/// Weight the equal diff with the smallest mv magnitude from the 
            /// predicted mv. 
						if(blkDiff == minDiffL2)
						{
              int currX = mx + rmx - predX2; int currY = my + rmy - predY2;
              int newX  = mx + j - predX2;   int newY  = my + i - predY2;
							if( ((currY*currY)+(currX*currX)) < ((newY*newY)+(newX*newX)) )
								goto MEH264IMCV2_LEVEL2_BREAK;
						}//end if blkDiff...
			
						minDiffL2 = blkDiff;
						rmx = j; rmy = i;
            _distVector.AddFirstIn((double)blkDiff);
            _xVector.AddFirstIn((double)(j + mx));
            _yVector.AddFirstIn((double)(i + my));
					}//end if blkDiff...
			
					MEH264IMCV2_LEVEL2_BREAK: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

      /// Select the smallest magnitude vector from the list of best winners.
//      GetSmallestVector(&_xVector, &_yVector, predX2, predY2, &mx, &my);
      GetBestVector(&_distVector,&_xVector, &_yVector, lambda, 16.0, 2, predX2, predY2, &mx, &my);

			mx = mx << 1; ///< Convert level 2 full pel units to level 1 full pel units ( x2 ).
			my = my << 1;
		}//end if _mode == 2...

		///----------------------- Level 1 full pel search --------------------------------
		/// Level 1: Set the input and ref blocks.
		_pInL1Over->SetOrigin(q,p);
		_pExtRefL1Over->SetOrigin(mx+q,my+p);

		/// Absolute/square diff comparison method.
#ifdef MEH264IMCV2_ABS_DIFF
		int minDiffL1 = _pInL1Over->Tad8x8(*_pExtRefL1Over);
#else
		int minDiffL1 = _pInL1Over->Tsd8x8(*_pExtRefL1Over);
#endif

    /// Initialise the fifos with the zero vector.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn((double)mx); _yVector.AddFirstIn((double)my); _distVector.AddFirstIn((double)minDiffL1);

    /// Level 1: Search on a cross pel grid over the defined L1 motion range if mode != 2. Otherwise
		///					 the range is a refinement if Level 2 was done (_mode = 2).
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;

		/// For mode = 2 (level 2 search has been done) do a refinement search.
		if(_mode == 2)
		{
			GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange, 1);

			for(i = yuRng; i <= ydRng; i++)
			{
				for(j = xlRng; j <= xrRng; j++)
				{
					int blkDiff;
					/// Early exit because zero (centre) motion vec already checked.
					if( !(i||j) )	goto MEH264IMCV2_LEVEL1_BREAK;

					/// Set the block to the [j,i] motion vector around the [mx+p,my+q] reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH264IMCV2_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest mv magnitude from the predicted mv. 
						if(blkDiff == minDiffL1)
						{
              int currX = mx + rmx - predX1; int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;   int newY  = my + i - predY1;
							if( ((currY*currY)+(currX*currX)) < ((newY*newY)+(newX*newX)) )
								goto MEH264IMCV2_LEVEL1_BREAK;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j; rmy = i;
            _distVector.AddFirstIn((double)blkDiff);
            _xVector.AddFirstIn((double)(j + mx));
            _yVector.AddFirstIn((double)(i + my));
					}//end if blkDiff...

					MEH264IMCV2_LEVEL1_BREAK: ; ///< null.
				}//end for j...
			}//end for i...

			/// Update new centre of winning vector.
			mx += rmx;
			my += rmy;
		}//end if mode == 2...
		else	///< Do a cross search.
		{
			/// For this case, this is the first entry point of the search i.e. (mx,my) = (0,0).

			for(int w = _l1MotionRange/2 ;w > 0; w = w/2)	///< Start at half the motion range and then converge by 2 every iteration.
			{
				/// The winning centre is readjusted on every loop therefore the ranges must be recalculated.
				GetMotionRange(q, p, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, lclL1MotionRange-1, 1);

				/// Reset the offset from (mx,my);
				rmx = 0;
				rmy = 0;
				for(int x = 0; x < MEH264IMCV2_MOTION_CROSS_POS_LENGTH; x++)
				{
					i = w * MEH264IMCV2_CrossPos[x].y;
					j = w * MEH264IMCV2_CrossPos[x].x;
					int blkDiff;

					/// Check that this offset is within the range of the image boundaries. If not then skip.
					if( ((i+my) < yuRng)||((i+my) > ydRng)||((j+mx) < xlRng)||((j+mx) > xrRng) )
						goto MEH264IMCV2_LEVEL1_BREAK_C;

					/// Set the block to the (j,i) motion vector around the (mx+p,my+q) reference location.
					_pExtRefL1Over->SetOrigin(j+mx+q, i+my+p);

#ifdef MEH263IMC_ABS_DIFF
					blkDiff = _pInL1Over->Tad8x8LessThan(*_pExtRefL1Over, minDiffL1);
#else
					blkDiff = _pInL1Over->Tsd8x8PartialLessThan(*_pExtRefL1Over, minDiffL1);
#endif
					if(blkDiff <= minDiffL1)
					{
						/// Weight the equal diff with the smallest motion vector magnitude. 
						if(blkDiff == minDiffL1)
						{
              int currX = mx + rmx - predX1; int currY = my + rmy - predY1;
              int newX  = mx + j - predX1;   int newY  = my + i - predY1;
							if( ((currY*currY)+(currX*currX)) < ((newY*newY)+(newX*newX)) )
								goto MEH264IMCV2_LEVEL1_BREAK_C;
						}//end if blkDiff...

						minDiffL1 = blkDiff;
						rmx = j; rmy = i;
            _distVector.AddFirstIn((double)blkDiff);
            _xVector.AddFirstIn((double)(j + mx));
            _yVector.AddFirstIn((double)(i + my));
					}//end if blkDiff...

					MEH264IMCV2_LEVEL1_BREAK_C: ; ///< null.

				}//end for x...

				/// Update new centre of winning vector.
				mx += rmx;
				my += rmy;
			}//end for w...

		}//end else...

    /// Select the best vector from the list of best winners.
    GetBestVector(&_distVector,&_xVector, &_yVector, lambda, 64.0, 1, predX1, predY1, &mx, &my);

		mx = mx << 1; ///< Convert level 1 full pel units to level 0 full pel units ( x2 ).
		my = my << 1;

		///----------------------- Level 0 full pel refined search ------------------------
    /// Level 0: Search on a full pel grid over the defined L0 refined motion range.

		/// Get the min diff at this location in level 0 grid units only if (mx,my) is not the zero mv because minDiff
    /// was initialised to zeroVecDiff at the start.
		_pExtRefOver->SetOrigin(n+mx,m+my);

    if(mx||my)
    {
#ifdef MEH264IMCV2_ABS_DIFF
		  minDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  minDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end if mx...

    /// Initialise the fifos with the current best vector.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn((double)mx); _yVector.AddFirstIn((double)my); _distVector.AddFirstIn((double)minDiff);

		/// Look for an improvement on the motion vector calc above within the refined range.
		rmx = 0;	///< Refinement motion vector centre.
		rmy = 0;
		GetMotionRange(n, m, mx, my, &xlRng, &xrRng, &yuRng, &ydRng, MEH264IMCV2_L0_MOTION_VECTOR_REFINED_RANGE, 0);

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
				int blkDiff;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IMCV2_LEVEL0_BREAK;

				/// Set the block to the [j,i] motion vector around the [n+mx,m+my] reference location.
				_pExtRefOver->SetOrigin(n+mx+j, m+my+i);

#ifdef MEH264IMCV2_ABS_DIFF
				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
#else
				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff with the smallest global mv magnitude from the pred mv. 
					if(blkDiff == minDiff)
					{
            int currX = mx + rmx - predX0Rnd; int currY = my + rmy - predY0Rnd;
            int newX  = mx + j - predX0Rnd;   int newY  = my + i - predY0Rnd;
						if( ((currY*currY)+(currX*currX)) < ((newY*newY)+(newX*newX)) )
							goto MEH264IMCV2_LEVEL0_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					rmx = j; rmy = i;
          _distVector.AddFirstIn((double)blkDiff);
          _xVector.AddFirstIn((double)(j + mx));
          _yVector.AddFirstIn((double)(i + my));
				}//end if blkDiff...

				MEH264IMCV2_LEVEL0_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

		/// Add the refinement in full pixel units.
		mx += rmx;
		my += rmy;

    /// Select the best vector from the list of best winners.
    int listPos = GetBestVector(&_distVector,&_xVector, &_yVector, lambda, 256.0, 0, predX0Rnd, predY0Rnd, &mx, &my);
    minDiff = (int)_distVector.GetItem(listPos);

		///----------------------- Level 0 quarter pel refined search ------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

    /// Initialise the fifos with the current best vector in 1/4 pel units.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn((double)mvx); _yVector.AddFirstIn((double)mvy); _distVector.AddFirstIn((double)minDiff);

		/// Set the location to the min diff motion vector (mx,my).
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IMCV2_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IMCV2_SubPos[x].x;
			int qOffY = 2 * MEH264IMCV2_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
		int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
        _distVector.AddFirstIn((double)blkDiff);
        _xVector.AddFirstIn((double)(qOffX + mvx));
        _yVector.AddFirstIn((double)(qOffY + mvy));
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IMCV2_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IMCV2_SubPos[x].x;
			int qOffY = hmy + MEH264IMCV2_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IMCV2_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
        _distVector.AddFirstIn((double)blkDiff);
        _xVector.AddFirstIn((double)(qOffX + mvx));
        _yVector.AddFirstIn((double)(qOffY + mvy));
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		///----------------------- Level 0 quarter pel pred vector ------------------------
    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 4) + predXQuart;
    predY = (predY0 * 4) + predYQuart;

    /// Select the best vector at 1/4 pel units from the previous refinement.
    listPos = GetBestVector(&_distVector,&_xVector, &_yVector, lambda, 256.0, 2, predX, predY, &mvx, &mvy);
    minDiff = (int)_distVector.GetItem(listPos);

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int predVecDiff = 0;
    /// Quarter read first if necessary.
    if(predXQuart || predYQuart)
    {
			/// Read the quarter grid pels into temp.
			_pExtRefOver->QuarterRead(*_pMBlkOver, predXQuart, predYQuart);
		/// Absolute/square diff comparison method.
#ifdef MEH264IMCV2_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
#endif
    }//end if predXQuart...
    else
    {
#ifdef MEH264IMCV2_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end else...

    /// Initialise the fifos and load the zero vector, pred vector and the curr best vector.
    _xVector.MarkAsEmpty(); _yVector.MarkAsEmpty(); _distVector.MarkAsEmpty();
    _xVector.AddFirstIn(0.0); _yVector.AddFirstIn(0.0); _distVector.AddFirstIn((double)zeroVecDiff);
    _xVector.AddFirstIn((double)predX); _yVector.AddFirstIn((double)predY); _distVector.AddFirstIn((double)predVecDiff);
    _xVector.AddFirstIn((double)mvx); _yVector.AddFirstIn((double)mvy); _distVector.AddFirstIn((double)minDiff);
    /// Use a cost function to select the best of the set. Parameter level = 2 gives best results.
    int vpos = GetBestVector(&_distVector, &_xVector, &_yVector, lambda, 256.0, 2, predX, predY, &mvx, &mvy);

		/// Check for inclusion in the distortion calculation.
		if(_pDistortionIncluded != NULL)
    {
      mvx = (int)_xVector.GetItem(vpos);
      mvy = (int)_yVector.GetItem(vpos);
			if(_pDistortionIncluded[vecPos])
      {
			  included++;
        totalDifference += (int)_distVector.GetItem(vpos);
      }//end if _pDistortionIncluded...
    }//end if _pDistortionIncluded...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
      /// Set macroblock vector for future predictions.
      _pMVPred->Set16x16MotionVector(vecPos, mvx, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplMultiresCrossVer2::Destroy(void)
{
	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pInL1 != NULL)
		delete[] _pInL1;
	_pInL1 = NULL;

	if(_pInL1Over != NULL)
		delete _pInL1Over;
	_pInL1Over = NULL;

	if(_pInL2 != NULL)
		delete[] _pInL2;
	_pInL2 = NULL;

	if(_pInL2Over != NULL)
		delete _pInL2Over;
	_pInL2Over = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pRefL1 != NULL)
		delete[] _pRefL1;
	_pRefL1	= NULL;

	if(_pRefL1Over != NULL)
		delete _pRefL1Over;
	_pRefL1Over	= NULL;

	if(_pExtRefL1 != NULL)
		delete[] _pExtRefL1;
	_pExtRefL1 = NULL;

	if(_pExtRefL1Over != NULL)
		delete _pExtRefL1Over;
	_pExtRefL1Over = NULL;

	if(_pRefL2 != NULL)
		delete[] _pRefL2;
	_pRefL2	= NULL;

	if(_pRefL2Over != NULL)
		delete _pRefL2Over;
	_pRefL2Over	= NULL;

	if(_pExtRefL2 != NULL)
		delete[] _pExtRefL2;
	_pExtRefL2 = NULL;

	if(_pExtRefL2Over != NULL)
		delete _pExtRefL2Over;
	_pExtRefL2Over = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCrossVer2::GetMotionRange(int  x,			int  y, 
																													int* xlr,		int* xrr, 
																													int* yur,		int* ydr,
																													int	 range,	int	 level)
{
	/// The level defines the members to use.
	int boundary, width, height;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IMCV2_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IMCV2_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IMCV2_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			break;
	}//end switch level...

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@param level		: Resolution level to operate.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCrossVer2::GetMotionRange(	int  xpos,	int  ypos,
																														int	 xoff,	int  yoff,
																														int* xlr,		int* xrr, 
																														int* yur,		int* ydr,
																														int	 range,	int	 level)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	/// The level defines the members to use.
	int boundary, width, height, vecRange;
	switch(level)
	{
		case 1 :
			boundary	= _extL1Boundary - MEH264IMCV2_L1_PADDING;
			width			= _l1Width;
			height		= _l1Height;
			vecRange	= _l1MotionRange;
			break;
		case 2 :
			boundary	= _extL2Boundary - MEH264IMCV2_L2_PADDING;
			width			= _l2Width;
			height		= _l2Height;
			vecRange	= _l2MotionRange;
			break;
		case 0 :
		default :
			boundary	= _extBoundary - MEH264IMCV2_PADDING;
			width			= _imgWidth;
			height		= _imgHeight;
			vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.
			break;
	}//end switch level...

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplMultiresCrossVer2::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IMCV2_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IMCV2_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IMCV2_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...

    /// One further "h" and "G" col at the end of the row.
		/// "h"
		window[quartRow+2][quartCol] = MEH264IMCV2_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];

	}//end fullRow...

   /// One further "b" and "G" row at the end.
	for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
	{
		/// "b"
		window[quartRow][quartCol+2] = MEH264IMCV2_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];
	}//end for fullCol...

  /// ...and one final "G" full pel at the bottom right edge.
	window[quartRow][quartCol] = ref[refRow][refCol];

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultiresCrossVer2::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplMultiresCrossVer2::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.




========== END FILE: CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.h ==========
Bundle entry: 96
Original bytes: 12067
Original SHA-256: 69fd71e67f59c8366cfc5af5f302d5b68893c92be6a0d83b8617135f092abdc6
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplMultiresCrossVer2

TAG						: MEH264IMCV2

FILE NAME			: MotionEstimatorH264ImplMultiresCrossVer2.h

DESCRIPTION		: A fast unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) with both absolute error 
								difference and square error measure. Access is via an 
								IMotionEstimator interface. There are 2 mode levels of 
								execution speed vs. quality. The boundary is extended to 
								accomodate the selected motion range. The estimation is
								performed on lower resolution representations and at the 
								lowest resolution a cascaded cross search is performed.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLMULTIRESCROSSVER2_H
#define _MOTIONESTIMATORH264IMPLMULTIRESCROSSVER2_H

#include "IMotionEstimator.h"
#include "IMotionVectorPredictor.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"
#include "GeneralUtils/Fifo.h"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IMCV2_COORD
{
	short int x;
	short int y;
} MEH264IMCV2_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplMultiresCrossVer2 : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplMultiresCrossVer2(	const void*             pSrc, 
																		        const void*             pRef, 
																		        int					            imgWidth, 
																		        int					            imgHeight,
																		        int					            motionRange,
                                            IMotionVectorPredictor* pMVPred);

	MotionEstimatorH264ImplMultiresCrossVer2(	const void*             pSrc, 
																		        const void*             pRef, 
																		        int					            imgWidth, 
																		        int					            imgHeight,
																		        int					            motionRange,
                                            IMotionVectorPredictor* pMVPred,
																		        void*				            pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplMultiresCrossVer2(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
	virtual void	Reset(void);
	virtual int		Ready(void)		{ return(_ready); }
	virtual void	SetMode(int mode);
	virtual int		GetMode(void) { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		        : Input image to estimate.
	@param pRef		        : Ref to estimate with.
  @param avgDistortion  : Return the average distortion of the estimation.
  @param constraint     : Apply an optimisation constraint to the estimation.
	@return				        : The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);
	virtual void* Estimate(long* avgDistortion, void* param);

/// Local methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range,	int		level); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

  /// Select the smallest magnitude vector from a list of x, y and distortion ordered vectors. The
  /// euclidian distance is measured from a reference vector. Return the list index of the 
  /// smallest vector. The values of mx & my are assumed to be copies of the vector from the top
  /// of the list at pos = 0.
  int GetSmallestVector(Fifo* x, Fifo* y, int xref, int yref, int* mx, int* my)
  {
    int pos = 0;
    int vecLen = (int)x->GetLength();  ///< Assume x & y have the same length.
    for(int ii = 1; ii < vecLen; ii++)
    {
      int xVec = (int)x->GetItem(ii);
      int yVec = (int)y->GetItem(ii);
      int ax = xVec - xref;
      int ay = yVec - yref;
      int bx = (*mx) - xref;
      int by = (*my) - yref;
      if( ((ax*ax)+(ay*ay)) < ((bx*bx)+(by*by)) )
      {
        (*mx) = xVec;
        (*my) = yVec;
        pos = ii;
      }//end if 
    }//end for ii...

    return(pos);
  }//end GetSmallestVector.
  /// Get vector that minimised a cost function.
  int GetBestVector(Fifo* d, Fifo* x, Fifo* y, double lambda, double norm, int level, int xref, int yref, int* mx, int* my)
  {
    double lclLambda = (lambda * (double)(1 << (level + 2)))/16.0;
    int pos     = 0;
    int vecLen  = (int)x->GetLength();  ///< Assume d, x & y have the same length.
    double currMag  = (double)( (((*mx) - xref)*((*mx) - xref)) + (((*my) - yref)*((*my) - yref)) );
    double currDist = d->GetItem(0);
    double currCost = (currDist/norm) + (lclLambda*sqrt(currMag));

    for(int ii = 1; ii < vecLen; ii++)
    {
      int xVec = (int)x->GetItem(ii);
      int yVec = (int)y->GetItem(ii);
      double newMag  = (double)(((xVec - xref)*(xVec - xref)) + ((yVec - yref)*(yVec - yref)));
      double newDist = d->GetItem(ii);
      double newCost = (newDist/norm) + (lambda*sqrt(newMag));
      if( newCost < currCost )
      {
        (*mx)     = xVec;
        (*my)     = yVec;
        currMag   = newMag;
        currDist  = newDist;
        currCost  = newCost;
        pos       = ii;
      }//end if newCost...

    }//end for ii...

    return(pos);
  }//end GetBestVector.

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Level 0: Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.
	/// Level 1: Subsampled input by 2. [_mode == 1]
	short*						_pInL1;						///< Input mem at (_l1Width * _l1Height).
	int								_l1Width;
	int								_l1Height;
	int								_l1MacroBlkWidth;
	int								_l1MacroBlkHeight;
	int								_l1MotionRange;		///< Full pel level 1 units.
	OverlayMem2Dv2*		_pInL1Over;				///< Input overlay with level 1 motion block dim.
	/// Level 2: Subsampled input by 4.	[_mode == 2]
	short*						_pInL2;						///< Input mem at (_l2Width * _l2Height).
	int								_l2Width;
	int								_l2Height;
	int								_l2MacroBlkWidth;
	int								_l2MacroBlkHeight;
	int								_l2MotionRange;		///< Full pel level 2 units.
	OverlayMem2Dv2*		_pInL2Over;				///< Input overlay with level 2 motion block dim.

	/// Level 0: Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.
	/// Level 1: Subsampled ref by 2.		[_mode == 1]
	short*							_pRefL1;					///< Ref mem at (_l1Width * _l1Height).
	OverlayMem2Dv2*			_pRefL1Over; 			///< Ref overlay with whole level 1 block dim.
	short*							_pExtRefL1;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL1Width;
	int									_extL1Height;
	int									_extL1Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL1Over;		///< Ref overlay with level 1 motion block dim.
	/// Level 2: Subsampled ref by 4.		[_mode == 2]
	short*							_pRefL2;					///< Ref mem at (_l2Width * _l2Height).
	OverlayMem2Dv2*			_pRefL2Over; 			///< Ref overlay with whole level 2 block dim.
	short*							_pExtRefL2;				///< Extended ref mem create by ExtendBoundary() call.
	int									_extL2Width;
	int									_extL2Height;
	int									_extL2Boundary;		///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefL2Over;		///< Ref overlay with level 2 motion block dim.
	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

  /// Fifos to store intermediate results.
  Fifo  _xVector; 
  Fifo  _yVector; 
  Fifo  _distVector; 

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;
  /// Attached motion vector predictor on construction.
  IMotionVectorPredictor* _pMVPred;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;
};//end MotionEstimatorH264ImplMultiresCrossVer2.


#endif // !_MOTIONESTIMATORH264IMPLMULTIRESCROSSVER2_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplMultiresCrossVer2.h ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplTest.cpp ==========
Bundle entry: 97
Original bytes: 41991
Original SHA-256: 1144c6b37afd74ec47770d1fd4a2de4ae167f7cca9867952debf3e3727520730
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplTest

TAG						: MEH264IT

FILE NAME			: MotionEstimatorH264ImplTest.cpp

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) for testing new algorithms. 
                Access is via an IMotionEstimator interface. The boundary 
                is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include	"MotionEstimatorH264ImplTest.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
/// Calc = ((16[vec dim] * 16[vec dim]) * 2.
#define MEH264IT_FULL_MOTION_NOISE_FLOOR				512
#define MEH264IT_MOTION_NOISE_FLOOR							 26 //24 //sqrt 512

/// Boundary padding past the motion vector extremes. Required for calculating
/// sub-pixel interpolations. 
#define MEH264IT_PADDING													3	

/// Choose between sqr err distortion or abs diff metric.
#undef MEH264IT_ABS_DIFF

/// Search range coords for centre motion vectors.
#define MEH264IT_MOTION_SUB_POS_LENGTH 	8
MEH264IT_COORD MEH264IT_SubPos[MEH264IT_MOTION_SUB_POS_LENGTH]	= 
{
	{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}
};

/*
--------------------------------------------------------------------------
  Macros. 
--------------------------------------------------------------------------
*/
#define MEH264IT_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

/*
--------------------------------------------------------------------------
  Construction. 
--------------------------------------------------------------------------
*/

MotionEstimatorH264ImplTest::MotionEstimatorH264ImplTest(	const void*             pSrc, 
																													const void*             pRef, 
																													int					            imgWidth, 
																													int					            imgHeight,
																													int					            motionRange,
                                                          IMotionVectorPredictor* pMVPred)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= imgWidth;					///< Width of the src and ref images. 
	_imgHeight			= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth	= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight	= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange		= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput					= pSrc;
	_pRef						= pRef;
  _pMVPred        = pMVPred;

}//end constructor.

MotionEstimatorH264ImplTest::MotionEstimatorH264ImplTest(	const void*             pSrc, 
																													const void*             pRef, 
																													int					            imgWidth, 
																													int					            imgHeight,
																													int					            motionRange,
                                                          IMotionVectorPredictor* pMVPred,
																													void*				            pDistortionIncluded)
{
	ResetMembers();

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth							= imgWidth;					///< Width of the src and ref images. 
	_imgHeight						= imgHeight;				///< Height of the src and ref images.
	_macroBlkWidth				= 16;								///< Width of the motion block = 16 for H.263.
	_macroBlkHeight				= 16;								///< Height of the motion block = 16 for H.263.
	_motionRange					= motionRange;			///< (4x,4y) range of the motion vectors. _motionRange in 1/4 pel units.
	_pInput								= pSrc;
	_pRef									= pRef;
  _pMVPred              = pMVPred;
	_pDistortionIncluded	= (bool *)pDistortionIncluded;

}//end constructor.

void MotionEstimatorH264ImplTest::ResetMembers(void)
{
	_ready	= 0;	///< Ready to estimate.
	_mode		= 1;	///< Speed mode or whatever. Default to slower speed.

	/// Parameters must remain const for the life time of this instantiation.
	_imgWidth				= 0;					///< Width of the src and ref images. 
	_imgHeight			= 0;					///< Height of the src and ref images.
	_macroBlkWidth	= 16;					///< Width of the motion block = 16 for H.264.
	_macroBlkHeight	= 16;					///< Height of the motion block = 16 for H.264.
	_motionRange		= 64;					///< (4x,4y) range of the motion vectors.
	_pInput					= NULL;
	_pRef						= NULL;

	/// Input mem overlay members.
	_pInOver					= NULL;			///< Input overlay with mb motion block dim.
	/// Ref mem overlay members.
	_pRefOver					= NULL;			///< Ref overlay with whole block dim.
	_pExtRef					= NULL;			///< Extended ref mem created by ExtendBoundary() call.
	_extWidth					= 0;
	_extHeight				= 0;
	_extBoundary			= 0;
	_pExtRefOver			= NULL;			///< Extended ref overlay with motion block dim.
  /// A 1/4 pel refinement window.
	_pWin							= NULL;
	_Win							= NULL;

	/// Temp working block and its overlay.
	_pMBlk						= NULL;			///< Motion block temp mem.
	_pMBlkOver				= NULL;			///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	_pMotionVectorStruct = NULL;
  /// Attached motion vector predictor on construction.
  _pMVPred             = NULL;

	/// A flag per macroblock to include it in the distortion accumulation.
	_pDistortionIncluded = NULL;

  /// Measurements.
  _METableLen = 0;
  _METablePos = 0;

}//end ResetMembers.

MotionEstimatorH264ImplTest::~MotionEstimatorH264ImplTest(void)
{
	Destroy();
}//end destructor.

/*
--------------------------------------------------------------------------
  Public IMotionEstimator Interface. 
--------------------------------------------------------------------------
*/

int MotionEstimatorH264ImplTest::Create(void)
{
	/// Clean out old mem.
	Destroy();

	/// --------------- Configure input overlays --------------------------------
	/// Put an overlay on the input image with the block size set to the mb vector 
	/// dim. This is used to access input vectors.
	_pInOver = new OverlayMem2Dv2((void *)_pInput,_imgWidth,_imgHeight,_macroBlkWidth,_macroBlkHeight);
	if(_pInOver == NULL)
	{
		Destroy();
		return(0);
	}//end _pInOver...

	/// --------------- Configure ref overlays --------------------------------
	/// Overlay the whole reference. The reference will have an extended 
	/// boundary for motion estimation and must therefore create its own mem.
	_pRefOver = new OverlayMem2Dv2((void *)_pRef, _imgWidth, _imgHeight, _imgWidth, _imgHeight);
	if(_pRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pRefOver...

	/// Create the new extended boundary ref into _pExtRef. The boundary is extended by
	/// the max dimension of the macroblock plus some padding to cater for quarter pel
  /// searches on the edges of the boundary. The mem is allocated in the method call.
	_extBoundary = _macroBlkWidth + MEH264IT_PADDING;
	if(_macroBlkHeight > _macroBlkWidth)
		_extBoundary = _macroBlkHeight + MEH264IT_PADDING;
	if(!OverlayExtMem2Dv2::ExtendBoundary((void *)_pRef, 
																				_imgWidth,						
																				_imgHeight, 
																				_extBoundary,	///< Extend left and right by...
																				_extBoundary,	///< Extend top and bottom by...
																				(void **)(&_pExtRef)) )	///< Created in the method and returned.
  {
		Destroy();
	  return(0);
  }//end if !ExtendBoundary...
	_extWidth	 = _imgWidth + (2 * _extBoundary);
	_extHeight = _imgHeight + (2 * _extBoundary);

	/// Place an overlay on the extended boundary ref with block size set to the mb motion 
  /// vec dim.
	_pExtRefOver = new OverlayExtMem2Dv2(	_pExtRef,				///< Src description created in the ExtendBoundary() call. 
																				_extWidth, 
																				_extHeight,
																				_macroBlkWidth,	///< Block size description.
																				_macroBlkHeight,
																				_extBoundary,		///< Boundary size for both left and right.
																				_extBoundary  );
	if(_pExtRefOver == NULL)
  {
		Destroy();
	  return(0);
  }//end if !_pExtRefOver...

	/// --------------- Configure temp overlays --------------------------------
	/// Alloc some temp mem and overlay it to use for half/quarter pel motion 
  /// estimation and compensation. The block size is the same as the mem size.
	_pMBlk = new short[_macroBlkWidth * _macroBlkHeight];
	_pMBlkOver = new OverlayMem2Dv2(_pMBlk, _macroBlkWidth, _macroBlkHeight, 
																					_macroBlkWidth, _macroBlkHeight);
	if( (_pMBlk == NULL)||(_pMBlkOver == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pMBlk...

	/// --------------- Configure result ---------------------------------------
	/// The structure container for the motion vectors.
	_pMotionVectorStruct = new VectorStructList(VectorStructList::SIMPLE2D);
	if(_pMotionVectorStruct != NULL)
	{
		/// How many motion vectors will there be at the block dim.
		int numVecs = (_imgWidth/_macroBlkWidth) * (_imgHeight/_macroBlkHeight);
		if(!_pMotionVectorStruct->SetLength(numVecs))
		{
			Destroy();
			return(0);
		}//end _pMotionVectorStruct...
	}//end if _pMotionVectorStruct...
	else
  {
		Destroy();
	  return(0);
  }//end if else...

	/// --------------- Refinement Window ---------------------------------------
	/// Prepare a 1/4 pel search window block for motion estimation refinement.
	int winWidth	= ((6 + _macroBlkWidth) * 4);
	int winHeight = ((6 + _macroBlkHeight) * 4);
	_pWin					= new short[winWidth * winHeight];
	_Win					= new OverlayMem2Dv2((void *)_pWin, winWidth, winHeight, winWidth, winHeight);
	if( (_pWin == NULL)||(_Win == NULL) )
  {
		Destroy();
	  return(0);
  }//end if !_pWin...

	/// --------------- Measurements ---------------------------------------
#ifdef MEH264IT_DUMP
  _METableLen = 16;
	_METable.Create(16, _METableLen);
  _METablePos = 0;

  /// Table is all integers and no headings.
  int i;
  for(i = 0; i < 16; i++)
  {
    _METable.SetHeading(i, "");
    _METable.SetDataType(i, MeasurementTable::INT);
  }//end for i...

  /// Zero the winner count and write into the coords of each 16x16 mb position.
  for(i = 0; i < 16; i++)
    for(int j = 0; j < 16; j++)
    {
      _winCount[i][j] = 0;
      _METable.WriteItem(j, i, _winCount[i][j]);
    }//end for i...

#endif

	_ready = 1;
	return(1);
}//end Create.

/** Motion estimate the source within the reference.
Do the estimation with the block sizes and image sizes defined in
the implementation. The returned type holds the vectors. This is
a full search algorithm with extended boundaries with a choice of
absolute difference or squared difference criterioa. 
@param avgDistortion  : Return the motion compensated distortion.
@return				        : The list of motion vectors.
*/
void* MotionEstimatorH264ImplTest::Estimate(long* avgDistortion)
{
  int		i,j,m,n,k,l;
	int		included = 0;
	long	totalDifference = 0;

	/// Set the motion vector struct storage structure.
	int		maxLength	= _pMotionVectorStruct->GetLength();
	int		vecPos		= 0;

	/// Write the ref and fill its extended boundary. The centre part of
	/// _pExtRefOver is copied from _pRefOver before filling the boundary.
	_pExtRefOver->SetOrigin(0, 0);
	_pExtRefOver->SetOverlayDim(_imgWidth, _imgHeight);
	_pExtRefOver->Write(*_pRefOver);	///< _pRefOver dimensions are always set to the whole image.
	_pExtRefOver->FillBoundaryProxy();
	_pExtRefOver->SetOverlayDim(_macroBlkWidth, _macroBlkHeight);

	/// Gather the motion vector absolute differnce/square error data and choose the vector.
	/// m,n step level 0 vec dim = _macroBlkHeight, _macroBlkWidth.
  for(m = 0; m < _imgHeight; m += _macroBlkHeight)
		for(n = 0; n < _imgWidth; n += _macroBlkWidth)
  {
		int mx	= 0;	///< Full pel grid.
		int my	= 0;
		int hmx	= 0;	///< 1/2 pel on 1/4 pel grid.
		int hmy	= 0;
		int qmx	= 0;	///< 1/4 pel grid.
		int qmy	= 0;
		int rmx = 0;	///< Refinement motion vector centre.
		int rmy = 0;

		/// Depending on which img boundary we are on will limit the full search range.
		int xlRng, xrRng, yuRng, ydRng;

		/// The predicted vector difference between the input and ref blocks is the most
		/// likely candidate and is therefore the starting best distortion point.
    int predX, predY, predX0Rnd, predY0Rnd;
    _pMVPred->Get16x16Prediction(NULL, vecPos, &predX, &predY);
    int predXQuart  = predX % 4;
    int predYQuart  = predY % 4;
    int predX0      = predX / 4;
    int predY0      = predY / 4;
    if(predX < 0)             ///< Nearest level 0 pred motion vector.
      predX0Rnd = (predX - 2)/4;
    else
      predX0Rnd = (predX + 2)/4;
    if(predY < 0)
      predY0Rnd = (predY - 2)/4;
    else
      predY0Rnd = (predY + 2)/4;

		/// Set the input and ref blocks to work with.
		_pInOver->SetOrigin(n,m);
		_pExtRefOver->SetOrigin(n,m);

		/// The (0,0) vector is the one to beat with Absolute/Square diff comparison method.
//#ifdef MEH264IT_ABS_DIFF
//		int zeroVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
//#else
//		int zeroVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
//#endif
    /// Total square diff between input and ref mb pels at mv position [0,0].
    int zeroVecDiff = 0;
    for(k = 0; k < _macroBlkHeight; k++)
      for(l = 0; l < _macroBlkWidth; l++)
      {
        int d = _pInOver->Read(l, k) - _pExtRefOver->Read(l, k);
        zeroVecDiff += (d*d);
      }//end for k & l...

		int minDiff	= zeroVecDiff;	///< Best so far.

    ///--------------------------- Full pel full grid search ---------------------------------------------------
    /// From this mb position determine the full pel search range permitted for the motion vector.
		GetMotionRange(n, m, 0, 0, &xlRng, &xrRng, &yuRng, &ydRng, _motionRange/4); ///< _motionRange is in 1/4 pel units and must be converted.

    for(i = yuRng; i <= ydRng; i++)
    {
			for(j = xlRng; j <= xrRng; j++)
			{
				int blkDiff;
				/// Early exit because zero motion vec already checked.
				if( !(i||j) )	goto MEH264IT_FULL_BREAK;

				/// Set the block to the [j,i] motion vector around the [n,m] reference location.
				_pExtRefOver->SetOrigin(n+j, m+i);

        /// Total square diff between input and ref mb pels at mv position [j,i].
        blkDiff = 0;
        for(k = 0; k < _macroBlkHeight; k++)
          for(l = 0; l < _macroBlkWidth; l++)
          {
            int d = _pInOver->Read(l, k) - _pExtRefOver->Read(l, k);
            blkDiff += (d*d);
            if(blkDiff > minDiff) goto MEH264IT_FULL_BREAK;
          }//end for k & l...

//#ifdef MEH264IT_ABS_DIFF
//				blkDiff = _pInOver->Tad16x16LessThan(*_pExtRefOver, minDiff);
//#else
////				blkDiff = _pInOver->Tsd16x16LessThan(*_pExtRefOver, minDiff);
//				blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pExtRefOver, minDiff);
//#endif
				if(blkDiff <= minDiff)
				{
					/// Weight the equal diff case with the smallest global mv magnitude from the pred mv. 
					if(blkDiff == minDiff)
					{
            int currX = mx - predX0Rnd;
            int currY = my - predY0Rnd;
            int newX  = j - predX0Rnd;
            int newY  = i + predY0Rnd;
						int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
						if(vecDistDiff < 0)
							goto MEH264IT_FULL_BREAK;
					}//end if blkDiff...

					minDiff = blkDiff;
					mx = j;
					my = i;
				}//end if blkDiff...

				MEH264IT_FULL_BREAK: ; ///< null.
			}//end for j...
    }//end for i...

    ///----------------------- Measurement collection --------------------------------------------
    /// The values of mx, my and minDiff above give the winning full search vector to compare with.

    /// We want to test the case where only 1 sample position in the mb is used for a full search to 
    /// find the best motion vector. This is a search for the 1st sample position in a sampling path. 
    /// The number of times each mb sample position gets the correct mv is accumulated in _winCount[].
    int tmx,tmy,tminDiff;
    for(k = 0; k < _macroBlkHeight; k++) ///< Full mv search for each sampling position in the mb.
      for(l = 0; l < _macroBlkWidth; l++)
      {
				/// Set the mb to the [0,0] motion vector around the [n,m] reference location.
				_pExtRefOver->SetOrigin(n, m);
        int d = _pInOver->Read(l, k) - _pExtRefOver->Read(l, k); ///< A single sample point inside mb.
        tminDiff = (d*d);
        tmx = 0;
        tmy = 0;
        /// Search all other non-zero motion vectors.
        for(i = yuRng; i <= ydRng; i++)
			    for(j = xlRng; j <= xrRng; j++)
          {
				    int tdiff;
				    /// Early exit because zero motion vec already checked.
				    if( !(i||j) )	goto MEH264IT_TEST_BREAK;
				    /// Set the mb to the [j,i] motion vector around the [n,m] reference location.
				    _pExtRefOver->SetOrigin(n+j, m+i);
            d = _pInOver->Read(l, k) - _pExtRefOver->Read(l, k); ///< A single sample point inside mb.
            tdiff= (d*d);
            /// Resolve best vector.
				    if(tdiff <= tminDiff)
				    {
					    /// Weight the equal diff case with the smallest global mv magnitude from the pred mv. 
					    if(tdiff == tminDiff)
					    {
                int currX = tmx - predX0Rnd;
                int currY = tmy - predY0Rnd;
                int newX  = j - predX0Rnd;
                int newY  = i + predY0Rnd;
						    int vecDistDiff = ( (currY*currY)+(currX*currX) )-( (newY*newY)+(newX*newX) );
						    if(vecDistDiff < 0)
							    goto MEH264IT_TEST_BREAK;
					    }//end if tdiff...

					    tminDiff = tdiff;
					    tmx = j;
					    tmy = i;
				    }//end if tdiff...

				    MEH264IT_TEST_BREAK: ; ///< null.
          }//end for i & j...

        /// Accumulate if same as full search mv for this [l,k] position and non-zero mv.
        if( (tmx == mx)&&(tmy == my)&&(tmx || tmy) )
        {
          _winCount[k][l]++;
          _METablePos = 16; ///< Validate the entire table after the 1st entry.
        }///end if tmx...

      }//end for k & l...

		///----------------------- Quarter pel refined search ----------------------------------------
    /// Search around the min diff full pel motion vector on a 1/4 pel grid firstly on the
		/// 1/2 pel positions and then refine the winner on the 1/4 pel positions. 

		int mvx = mx << 2;	///< Convert to 1/4 pel units.
		int mvy = my << 2;

		/// Set the location to the min diff motion vector (mx,my).
		_pExtRefOver->SetOrigin(n+mx, m+my);

		/// Fill the 1/4 pel window with valid values only in the 1/2 pel positions.
		LoadHalfQuartPelWindow(_Win, _pExtRefOver); 

    for(int x = 0; x < MEH264IT_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = 2 * MEH264IT_SubPos[x].x;
			int qOffY = 2 * MEH264IT_SubPos[x].y;

			/// Read the half grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IT_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
		int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				hmx = qOffX;
				hmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		qmx = hmx;
		qmy = hmy;

		/// Fill the 1/4 pel positions around the winning 1/2 pel position (hmx,hmy).
		LoadQuartPelWindow(_Win, hmx, hmy); 

    for(int x = 0; x < MEH264IT_MOTION_SUB_POS_LENGTH; x++)
    {
			int qOffX = hmx + MEH264IT_SubPos[x].x;
			int qOffY = hmy + MEH264IT_SubPos[x].y;

			/// Read the quarter grid pels into temp.
			QuarterRead(_pMBlkOver, _Win, qOffX, qOffY);

#ifdef MEH264IT_ABS_DIFF
			int blkDiff = _pInOver->Tad16x16LessThan(*_pMBlkOver, minDiff);
#else
//			int blkDiff = _pInOver->Tsd16x16LessThan(*_pMBlkOver, minDiff);
			int blkDiff = _pInOver->Tsd16x16PartialLessThan(*_pMBlkOver, minDiff);
#endif
			if(blkDiff < minDiff)
			{
				minDiff = blkDiff;
				qmx = qOffX;
				qmy = qOffY;
			}//end if blkDiff...
    }//end for x...

		/// Add the refinement in 1/4 pel units.
		mvx += qmx;
		mvy += qmy;

		/// Bounds check used for debugging only as the minDiff will not be correct.
		//if(mvx < -_motionRange) 
		//	mvx = -_motionRange;
		//else if(mvx >= _motionRange)
		//	mvx = (_motionRange-1);
		//if(mvy < -_motionRange) 
		//	mvy = -_motionRange;
		//else if(mvy >= _motionRange)
		//	mvy = (_motionRange-1);

		///----------------------- Quarter pel pred vector ----------------------------
    /// Compare this winning vector with the predicted mv but truncate it if it
    /// falls outside of one mb width or height outside the img boundaries.
    if( (predX0+n) > _imgWidth)
      predX0 = _macroBlkWidth;
    if( (predX0+n) < -_macroBlkWidth)
      predX0 = -_macroBlkWidth;
    if( (predY0+m) > _imgHeight)
      predY0 = _macroBlkHeight;
    if( (predY0+m) < -_macroBlkHeight)
      predY0 = -_macroBlkHeight;
    predX = (predX0 * 4) + predXQuart;
    predY = (predY0 * 4) + predYQuart;

		_pExtRefOver->SetOrigin(predX0+n,predY0+m);

    /// Get distortion at pred mv.
    int predVecDiff = 0;
    /// Quarter read first if necessary.
    if(predXQuart || predYQuart)
    {
			/// Read the quarter grid pels into temp.
			_pExtRefOver->QuarterRead(*_pMBlkOver, predXQuart, predYQuart);
		/// Absolute/square diff comparison method.
#ifdef MEH264IT_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pMBlkOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pMBlkOver);
#endif
    }//end if predXQuart...
    else
    {
#ifdef MEH264IT_ABS_DIFF
		  predVecDiff = _pInOver->Tad16x16(*_pExtRefOver);
#else
		  predVecDiff = _pInOver->Tsd16x16(*_pExtRefOver);
#endif
    }//end else...

		/// Selection of the final motion vector is weighted with non-linear factors. The
    /// zero vector will be modified to the best of either the predicted mv or the zero mv.
    int zeromvx, zeromvy;
    if(predVecDiff <= zeroVecDiff)
    {
      zeroVecDiff = predVecDiff;
      zeromvx     = predX;
      zeromvy     = predY;
    }//end if predVecDiff...
    else
    {
      zeromvx     = 0;
      zeromvy     = 0;
    }//end else...

		int diffWithZeroDiff	= zeroVecDiff - minDiff;
		int weight						= 0;
		int magSqr						= (mvx * mvx) + (mvy * mvy);

#ifdef MEH264IT_ABS_DIFF
		/// Contribute if motion vector is small.
		if((diffWithZeroDiff * 2) < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IT_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min diff vector are similar.
		if((diffWithZeroDiff * 7) < minDiff)
			weight++;
#else
		/// Contribute if motion vector is small.
		if(diffWithZeroDiff < magSqr)
			weight++;
		/// Contribute if same order as the noise.
		if(zeroVecDiff < MEH264IT_FULL_MOTION_NOISE_FLOOR)
			weight++;
		/// Contribute if the zero vector and min energy vector are similar.
		if((diffWithZeroDiff * 10) < minDiff)
			weight++;
#endif

		/// Check for inclusion in the distortion calculation.
		bool doIt = true;
		if(_pDistortionIncluded != NULL)
			doIt = _pDistortionIncluded[vecPos];
		if(doIt)
			included++;

		/// Decide whether or not to accept the final motion vector or revert to the zero/pred motion vector.
		if((minDiff < zeroVecDiff)&&(weight < 2))
    {
			if(doIt)
				totalDifference += minDiff;
    }//end if min_energy...
    else
		{
			mvx = zeromvx;
			mvy = zeromvy;
			if(doIt)
				totalDifference += zeroVecDiff;
		}//end else...

		/// Load the selected vector coord.
		if(vecPos < maxLength)
		{
			_pMotionVectorStruct->SetSimpleElement(vecPos, 0, mvx);
			_pMotionVectorStruct->SetSimpleElement(vecPos, 1, mvy);
      /// Set macroblock vector for future predictions.
      _pMVPred->Set16x16MotionVector(vecPos, mvx, mvy);
			vecPos++;
		}//end if vecPos...

  }//end for m & n...

	/// In this context avg distortion is actually avg difference.
//	*avgDistortion = totalDifference/maxLength;
	if(included)	///< Prevent divide by zero error.
		*avgDistortion = totalDifference/included;
	else
		*avgDistortion = 0;
	return((void *)_pMotionVectorStruct);

}//end Estimate.

/*
--------------------------------------------------------------------------
  Public methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplTest::Dump(const char* filename)
{
  if(_METablePos > 0)
    _METable.Save(filename, ",", 1);
  _METablePos = 0;
}//end Dump.

/*
--------------------------------------------------------------------------
  Private methods. 
--------------------------------------------------------------------------
*/

void MotionEstimatorH264ImplTest::Destroy(void)
{
  /// Save measuements before closing.
#ifdef MEH264IT_DUMP
  for(int i = 0; i < _METablePos; i++)
    for(int j = 0; j < 16; j++)
      _METable.WriteItem(j, i, _winCount[i][j]);
  if(_METablePos > 0)
    Dump(MEH264IT_PATH_DATA);
#endif
  _METable.Destroy();

	_ready = 0;

	if(_Win != NULL)
		delete _Win;
	_Win = NULL;
	if(_pWin != NULL)
		delete[] _pWin;
	_pWin = NULL;

	if(_pInOver != NULL)
		delete _pInOver;
	_pInOver = NULL;

	if(_pRefOver != NULL)
		delete _pRefOver;
	_pRefOver	= NULL;

	if(_pExtRef != NULL)
		delete[] _pExtRef;
	_pExtRef = NULL;

	if(_pExtRefOver != NULL)
		delete _pExtRefOver;
	_pExtRefOver = NULL;

	if(_pMBlk != NULL)
		delete[] _pMBlk;
	_pMBlk = NULL;

	if(_pMBlkOver != NULL)
		delete _pMBlkOver;
	_pMBlkOver = NULL;

	if(_pMotionVectorStruct != NULL)
		delete _pMotionVectorStruct;
	_pMotionVectorStruct = NULL;

}//end Destroy.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The returned values are offset limits from (x,y) image coordinate.
@param x				: X coord of block.
@param y				: Y coord of block.
@param xlr			: Returned allowed left range offset from x.
@param xrr			: Returned allowed right range offset from x.
@param yur			: Returned allowed up range offset from y.
@param ydr			: Returned allowed down range offset from y.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplTest::GetMotionRange( int  x,			int  y, 
																								  int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int boundary	= _extBoundary - MEH264IT_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;

	if( (x - range) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -range;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + range) < width )	///< Rest of block extends into the bounday region.
		*xrr = range;
	else
		*xrr = width - x;

	if( (y - range) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -range;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + range) < height )	///< Rest of block extends into the bounday region.
		*ydr = range;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Get the allowed motion range for this block.
The search area for unrestricted H.264 is within the bounds of the extended image
dimensions. The range is limited at the corners and edges of the extended
images. The range is further checked to ensure that the motion vector is within 
its defined max range. The returned values are offset limits from the (xpos+xoff,ypos+yoff) 
image coordinates.
@param xpos			: X coord of block in the image.
@param ypos			: Y coord of block in the image.
@param xoff			: Current offset (vector) from xpos.
@param yoff			: Current offset (vector) from ypos.
@param xlr			: Returned allowed left range offset from xpos+xoff.
@param xrr			: Returned allowed right range offset from xpos+xoff.
@param yur			: Returned allowed up range offset from ypos+yoff.
@param ydr			: Returned allowed down range offset from ypos+yoff.
@param range		: Desired range of motion.
@return					: none.
*/
void MotionEstimatorH264ImplTest::GetMotionRange(	int  xpos,	int  ypos,
																									int	 xoff,	int  yoff,
																									int* xlr,		int* xrr, 
																									int* yur,		int* ydr,
																									int	 range)
{
	int x = xpos + xoff;
	int y = ypos + yoff;

	int xLRange, xRRange, yURange, yDRange;

	int boundary	= _extBoundary - MEH264IT_PADDING;
	int	width			= _imgWidth;
	int	height		= _imgHeight;
	int	vecRange	= _motionRange/4;	///< Convert 1/4 pel range to full pel units.

	/// Limit the range of the motion vector.
	if( (xoff - range) > -vecRange )
		xLRange = range;
	else
		xLRange = (vecRange-1) + xoff;
	if( (xoff + range) < vecRange )
		xRRange = range;
	else
		xRRange = (vecRange-1) - xoff;
	if( (yoff - range) > -vecRange )
		yURange = range;
	else
		yURange = (vecRange-1) + yoff;
	if( (yoff + range) < vecRange )
		yDRange = range;
	else
		yDRange = (vecRange-1) - yoff;

	if( (x - xLRange) >= -boundary )	///< Ok and within left extended boundary.
		*xlr = -xLRange;
	else ///< Bring it into the extended boundary edge.
		*xlr = -(x + boundary);
	if( (x + xRRange) < width )	///< Rest of block extends into the bounday region.
		*xrr = xRRange;
	else
		*xrr = width - x;

	if( (y - yURange) >= -boundary )	///< Ok and within upper extended boundary.
		*yur = -yURange;
	else ///< Bring it into the extended boundary edge.
		*yur = -(y + boundary);
	if( (y + yDRange) < height )	///< Rest of block extends into the bounday region.
		*ydr = yDRange;
	else
		*ydr = height - y;

}//end GetMotionRange.

/** Load a 1/4 pel window with 1/2 pel values.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the first stage
and therefore only the 1/2 pel positions are valid. This method must be followed by the LoadQuartPelWindow()
method to complete the 1/4 pel values around a winning 1/2 pel position. The reference origin position is 
aligned onto the full pel (3,3) position of the 1/4 pel window.
@param qPelWin	: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param extRef		: Reference to derive the 1/4 pel window from.
@return					: none.
*/
void MotionEstimatorH264ImplTest::LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef)
{
	int fullRow, fullCol, quartRow, quartCol, refRow, refCol;

	int			width		= qPelWin->GetWidth()/4;	///< Convert to full pel units.
	int			height	= qPelWin->GetHeight()/4;
	short** window	= qPelWin->Get2DSrcPtr();

	short** ref			= extRef->Get2DSrcPtr();
	int			refXPos = extRef->GetOriginX();
	int			refYPos = extRef->GetOriginY();

	/// Set all the "h" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 2, quartRow = 10, refRow = refYPos - 1; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 0, quartCol = 0, refCol = refXPos - 3; fullCol < width; fullCol++, quartCol += 4, refCol++)
		{
			int h =     (int)ref[refRow-2][refCol] -  5*(int)ref[refRow-1][refCol] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow+1][refCol] - 
							  5*(int)ref[refRow+2][refCol] +    (int)ref[refRow+3][refCol];

			window[quartRow][quartCol] = (short)(h);
		}//end for fullCol...
	}//end fullRow...
	
	/// Set all the "b" half pel values in the window only at the positions that will be required for the other calcs. No
	/// scaling or clipping is performed until "j" half pel values are completed.
	for(fullRow = 0, quartRow = 0, refRow	= refYPos - 3; fullRow < height; fullRow++, quartRow += 4, refRow++)
	{
		for(fullCol = 2, quartCol = 10, refCol = refXPos - 1; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4, refCol++)
		{
			int b =     (int)ref[refRow][refCol-2] -  5*(int)ref[refRow][refCol-1] + 
							 20*(int)ref[refRow][refCol]   + 20*(int)ref[refRow][refCol+1] - 
							  5*(int)ref[refRow][refCol+2] +    (int)ref[refRow][refCol+3];

			window[quartRow][quartCol] = (short)(b);
		}//end for fullCol...
	}//end fullRow...

	/// For the "j" half pel values, use the previously calculated "h" and "b" values only in the positions
	/// surrounding the centre of the reference image origin. Now scaling is included for j.
	for(fullRow = 2, quartRow = 10; fullRow < (_macroBlkHeight + 3); fullRow++, quartRow += 4)
	{
		for(fullCol = 2, quartCol = 10; fullCol < (_macroBlkWidth + 3); fullCol++, quartCol += 4)
		{
			int j = (   (int)window[quartRow][quartCol-10] -  5*(int)window[quartRow][quartCol-6] + 
							 20*(int)window[quartRow][quartCol-2]  + 20*(int)window[quartRow][quartCol+2] - 
							  5*(int)window[quartRow][quartCol+6]  +    (int)window[quartRow][quartCol+10] + 512) >> 10;

			window[quartRow][quartCol] = (short)(MEH264IT_CLIP255(j));
		}//end for fullCol...
	}//end fullRow...

	/// Scale and clip the useful "h" and "b" half pel values in place.
	for(fullRow = 2, refRow	= refYPos - 1, quartRow = 8; fullRow < (_macroBlkHeight + 3); fullRow++, refRow++, quartRow += 4)
	{
		for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
		{
			/// "h"
			window[quartRow+2][quartCol] = MEH264IT_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
			/// "b"
			window[quartRow][quartCol+2] = MEH264IT_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
			/// Copy full pel "G"
			window[quartRow][quartCol] = ref[refRow][refCol];
		}//end for fullCol...

    /// One further "h" and "G" col at the end of the row.
		/// "h"
		window[quartRow+2][quartCol] = MEH264IT_CLIP255((window[quartRow+2][quartCol] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];

	}//end fullRow...

   /// One further "b" and "G" row at the end.
	for(fullCol = 2, refCol = refXPos - 1, quartCol = 8; fullCol < (_macroBlkWidth + 3); fullCol++, refCol++, quartCol += 4)
	{
		/// "b"
		window[quartRow][quartCol+2] = MEH264IT_CLIP255((window[quartRow][quartCol+2] + 16) >> 5);
		/// Copy full pel "G"
		window[quartRow][quartCol] = ref[refRow][refCol];
	}//end for fullCol...

  /// ...and one final "G" full pel at the bottom right edge.
	window[quartRow][quartCol] = ref[refRow][refCol];

}//end LoadHalfQuartPelWindow.

/** Load a 1/4 pel window with 1/4 pel values not in 1/2 pel positions.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. This window is used in a cascading 
approach to motion estimation where the best 1/2 pel search around a winning full pel is done first followed 
by the best 1/4 pel around the winning 1/2 pel position. This window is used for the input for the second stage
and therefore the 1/2 pel positions are valid from a previous (first stage) call to the LoadHalfQuartPelWindow() 
method. This method will complete the 1/4 pel values around a winning 1/2 pel position. The reference origin 
position is aligned onto the full pel (3,3) position of the 1/4 pel window. The 1/4 pel values are processed
from the values already in the window.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param hPelColOff	: The winning 1/2 pel X offset from the (3,3) window position in 1/4 pel units.
@param hPelRowOff	: The winning 1/2 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplTest::LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol;

	/// The 1/4 pels are to calculated for the 8 positions surrounding the 1/2 location at (hPelRowOff,hPelColOff). Note
	/// that hPelRowOff and hPelColOff are still in 1/4 pel units i.e. = range [-2,0,2][-2,0,2].

	short** window	= qPelWin->Get2DSrcPtr();

	for(fullRow = 0, quartRow = (12 + hPelRowOff); fullRow < _macroBlkHeight; fullRow++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + hPelColOff); fullCol < _macroBlkWidth; fullCol++, quartCol += 4)
		{
			window[quartRow-1][quartCol-1]	= (window[quartRow-2][quartCol-2] + window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol]		= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow-1][quartCol+1]	= (window[quartRow-2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
			window[quartRow][quartCol-1]		= (window[quartRow][quartCol-2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow][quartCol+1]		= (window[quartRow][quartCol+2]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol-1]	= (window[quartRow][quartCol-2]		+ window[quartRow+2][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol]		= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol] + 1) >> 1;
			window[quartRow+1][quartCol+1]	= (window[quartRow+2][quartCol]		+ window[quartRow][quartCol+2] + 1) >> 1;
		}//end for fullCol...
	}//end fullRow...

}//end LoadQuartPelWindow.

/** Read 1/4 pels from window.
The 1/4 pel window must be the macroblock size with a boundary of 3 extra pels on all sides. Only the inner
macroblock size plus 1 extra pel boundary are filled with valid values. Read a block from the window centred
on the (3,3) position with a 1/4 pel offset given by the input params into the destination block.
@param dstBlock		: Destination block.
@param qPelWin		: Window of size (4 * (_macroBlkHeight+6)) x (4 * (_macroBlkWidth+6))
@param qPelColOff	: The 1/4 pel X offset from the (3,3) window position in 1/4 pel units.
@param qPelRowOff	: The 1/4 pel Y offset from the (3,3) window position in 1/4 pel units.
@return						: none.
*/
void MotionEstimatorH264ImplTest::QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff)
{
	int fullRow, fullCol, quartRow, quartCol, dstX;

	short** window	= qPelWin->Get2DSrcPtr();	/// The origin of the window is around full pel position (3,3).

	short** dst			= dstBlock->Get2DSrcPtr();
	int			width		= dstBlock->GetWidth();
	int			height	= dstBlock->GetHeight();
	int			dstXPos = dstBlock->GetOriginX();
	int			dstYPos = dstBlock->GetOriginY();

	/// 1/4 pel rows and cols increment in quarter pel units with (3,3) full pel offset + input offset. As
	/// in: quartRow	= ((fullRow + 3) * 4) + qPelRowOff; and quartCol	= ((fullCol + 3) * 4) + qPelColOff;

	for(fullRow = 0, quartRow = (12 + qPelRowOff); fullRow < height; fullRow++, dstYPos++, quartRow += 4)
	{
		for(fullCol = 0, quartCol = (12 + qPelColOff), dstX = dstXPos; fullCol < width; fullCol++, quartCol += 4, dstX++)
			dst[dstYPos][dstX] = window[quartRow][quartCol];
	}//end fullRow...

}//end QuarterRead.






========== END FILE: CodecUtils/MotionEstimatorH264ImplTest.cpp ==========

========== BEGIN FILE: CodecUtils/MotionEstimatorH264ImplTest.h ==========
Bundle entry: 98
Original bytes: 7845
Original SHA-256: 2b7fac7f736a5a781d77b2eb945b63c1452938bc38a82d331a2f680c424f477e
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: MotionEstimatorH264ImplTest

TAG						: MEH264IT

FILE NAME			: MotionEstimatorH264ImplTest.h

DESCRIPTION		: A full unrestricted motion estimator implementation for 
								Recommendation H.264 (03/2005) for testing new algorithms. 
                Access is via an IMotionEstimator interface. The boundary 
                is extended to accomodate the selected motion range.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _MOTIONESTIMATORH264IMPLTEST_H
#define _MOTIONESTIMATORH264IMPLTEST_H

#include "IMotionEstimator.h"
#include "IMotionVectorPredictor.h"
#include "VectorStructList.h"
#include "OverlayMem2Dv2.h"
#include "OverlayExtMem2Dv2.h"

#include  "GeneralUtils/MeasurementTable.h"
//#undef MEH264IT_DUMP 
#define MEH264IT_DUMP 1 ///< Enable measurement dump.
/// Dump filename
#define MEH264IT_PATH_DATA "c:/keithf/Excel/VideoEvaluation/MotionEstimationPathData.csv"

/*
---------------------------------------------------------------------------
	Struct definition.
---------------------------------------------------------------------------
*/
typedef struct _MEH264IT_COORD
{
	short int x;
	short int y;
} MEH264IT_COORD;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class MotionEstimatorH264ImplTest : public IMotionEstimator
{
/// Construction.
public:

	MotionEstimatorH264ImplTest(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred);

	MotionEstimatorH264ImplTest(	const void*             pSrc, 
																const void*             pRef, 
																int					            imgWidth, 
																int					            imgHeight,
																int					            motionRange,
                                IMotionVectorPredictor* pMVPred,
																void*				            pDistortionIncluded);

	virtual ~MotionEstimatorH264ImplTest(void);

/// IMotionEstimator Interface.
public:
	virtual int		Create(void);
  virtual void	Reset(void)       {}
	virtual int		Ready(void)		    { return(_ready); }
  virtual void	SetMode(int mode) { _mode = mode; }
	virtual int		GetMode(void)     { return(_mode); }

	/** Motion estimate the source within the reference.
	Do the estimation with the block sizes and image sizes defined in
	the implementation. The returned type holds the vectors.
	@param pSrc		: Input image to estimate.
	@param pRef		: Ref to estimate with.
	@return				: The list of motion vectors.
	*/
	virtual void* Estimate(const void* pSrc, const void* pRef, long* avgDistortion)
		{ return(Estimate(avgDistortion)); }
	virtual void* Estimate(long* avgDistortion);

/// Local public methods.
public:

  void Dump(const char* filename);  ///< Requires MEH264IT_DUMP to be defined.

/// Local private methods.
protected:

	/// Used by constructors to reset every member.
	void ResetMembers(void);
	/// Clear alloc mem.
	void Destroy(void);
	/// Get the motion search range in the reference and limit it to the picture extended boundaries.
	void GetMotionRange(int		x,			int		y, 
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 
	/// Motion search range in the reference limited to the picture extended boundaries and max vector range.
	void GetMotionRange(int		x,			int		y,
											int		offx,		int		offy,
											int*	xlr,		int*	xrr, 
											int*	yur,		int*	ydr, 
											int		range); 

	void LoadHalfQuartPelWindow(OverlayMem2Dv2* qPelWin, OverlayMem2Dv2* extRef);
	void LoadQuartPelWindow(OverlayMem2Dv2* qPelWin, int hPelColOff, int hPelRowOff);
	void QuarterRead(OverlayMem2Dv2* dstBlock, OverlayMem2Dv2* qPelWin, int qPelColOff, int qPelRowOff);

protected:

	int _ready;	///< Ready to estimate.
	int _mode;	///< Speed mode or whatever. [ 0 = auto, 1 = level 1, 2 = level 2.]

	/// Parameters must remain const for the life time of this instantiation.
	int	_imgWidth;				///< Width of the src and ref images. 
	int	_imgHeight;				///< Height of the src and ref images.
	int	_macroBlkWidth;		///< Width of the motion block.
	int	_macroBlkHeight;	///< Height of the motion block.
	int	_motionRange;			///< (4x,4y) range of the motion vectors in 1/4 pel units.

	const void*	_pInput;	///< References to the images at construction.
	const void* _pRef;

	/// Input mem overlay members.
	OverlayMem2Dv2*		_pInOver;					///< Input overlay with motion block dim.

	/// Ref mem overlay members.
	OverlayMem2Dv2*			_pRefOver;				///< Ref overlay with whole block dim.
	short*							_pExtRef;					///< Extended ref mem created by ExtendBoundary() call.
	int									_extWidth;
	int									_extHeight;
	int									_extBoundary;			///< Extended boundary for left, right, up and down.
	OverlayExtMem2Dv2*	_pExtRefOver;			///< Extended ref overlay with motion block dim.

	/// A 1/4 pel refinement window.
	short*							_pWin;
	OverlayMem2Dv2*			_Win;

	/// Temp working block and its overlay.
	short*							_pMBlk;						///< Motion block temp mem.
	OverlayMem2Dv2*			_pMBlkOver;				///< Motion block overlay of temp mem.

	/// Hold the resulting motion vectors in a byte array.
	VectorStructList*	_pMotionVectorStruct;
  /// Attached motion vector predictor on construction.
  IMotionVectorPredictor* _pMVPred;

	/// A flag per macroblock to include it in the distortion accumulation.
	bool*							_pDistortionIncluded;

  /// Store tables of measurement data for research. 
  MeasurementTable  _METable;
  int               _METableLen;
  int               _METablePos;
#ifdef MEH264IT_DUMP
  int               _winCount[16][16];
#endif
};//end MotionEstimatorH264ImplTest.

#endif // !_MOTIONESTIMATORH264IMPLTEST_H

========== END FILE: CodecUtils/MotionEstimatorH264ImplTest.h ==========

========== BEGIN FILE: CodecUtils/NalHeaderH264.cpp ==========
Bundle entry: 99
Original bytes: 2724
Original SHA-256: 3a31be25fa46a19d65f5cc06b98604c37558620cb5194aae45cd85fc4568273a
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: NalHeaderH264

TAG						: NHH264

FILE NAME			: NalHeaderH264.cpp

DESCRIPTION		: A class to hold H.264 NAL header data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "NalHeaderH264.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
NalHeaderH264::NalHeaderH264(void)
{
	/// Defualt to an IDR NAL unit.
	_ref_idc		= 3;					///< Indicates reference parameter sets or IDR coded slices in the NAL payload. 
	_unit_type	= IDR_Slice;	///< NAL contents type.

}//end constructor.

NalHeaderH264::~NalHeaderH264(void)
{
}//end destructor.

========== END FILE: CodecUtils/NalHeaderH264.cpp ==========

========== BEGIN FILE: CodecUtils/NalHeaderH264.h ==========
Bundle entry: 100
Original bytes: 3422
Original SHA-256: 5010965e22d8c35854004a1fad28734ff55dd7c332bf28c067c64037f9c286f7
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: NalHeaderH264

TAG						: NHH264

FILE NAME			: NalHeaderH264.h

DESCRIPTION		: A class to hold H.264 NAL header data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _NALHEADERH264_H
#define _NALHEADERH264_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class NalHeaderH264
{
public:
	NalHeaderH264(void);
	virtual ~NalHeaderH264(void);

/// Public constants.
public:
	/// Payload types for _unit_type member.
	static const int Unspecified							= 0;
	static const int NonIDR_NoPartition_Slice	= 1;
	static const int NonIDR_PartitionA_Slice	= 2;
	static const int NonIDR_PartitionB_Slice	= 3;
	static const int NonIDR_PartitionC_Slice	= 4;
	static const int IDR_Slice								= 5;
	static const int SEI											= 6;
	static const int SeqParamSet							= 7;
	static const int PicParamSet							= 8;
	static const int AccessUnitDelimiter			= 9;
	static const int EndOfSeq									= 10;
	static const int EndOfStream							= 11;
	static const int FillerData								= 12;
	static const int SeqParamSetExt						= 13;
	/// 14..18 Reserved.
	static const int Aux_NoPartition_Slice		= 19;
	/// 20..23 Reserved.
	/// 24..31 Unspecified.

/// Public members.
public:
	int _ref_idc;				///< Indicates reference parameter sets or IDR coded slices in the NAL payload. 
	int _unit_type;			///< NAL contents type.

};// end class NalHeaderH264.

#endif	//_NALHEADERH264_H
========== END FILE: CodecUtils/NalHeaderH264.h ==========

========== BEGIN FILE: CodecUtils/PicParamSetH264.cpp ==========
Bundle entry: 101
Original bytes: 9736
Original SHA-256: 9180f90aedb55c626975227ff61857944f2272c0a5413427619053dcf56517f9
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: PicParamSetH264

TAG						: PPSH264

FILE NAME			: PicParamSetH264.cpp

DESCRIPTION		: A class to hold H.264 picture parameter set data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "PicParamSetH264.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
PicParamSetH264::PicParamSetH264(int pic_param_set_id)
{
	_pic_parameter_set_id										= pic_param_set_id;	///< The index for this definition of picture params [0..255].
	_seq_parameter_set_id										= -1;								///< This pic param set refers to this seq param set. Range = [0..31].

	_entropy_coding_mode_flag								= 0;								///< Baseline profile = 0. CAVLC/CABAC = 0/1.
	_pic_order_present_flag									= 0;								///< Pic order count syntax elements are present in the slice header.

	_num_slice_groups_minus1								= 0;								///< = 0 (baseline profile). Num of slice groups for a pic.
	_slice_group_map_type										= 0;								///< Defines map units to slice groups. Range = [0..6].
	/// Not initialised: _run_length_minus1[7];									///< Slice group mapping.
	/// Not initialised: _top_left[7];													///< Slice group mapping.
	/// Not initialised: _bottom_right[7];											///< Slice group mapping.
	_slice_group_change_direction_flag			= 0;								///< Slice group mapping.
	_slice_group_change_rate_minus1					= 0;								///< Slice group mapping.
	_pic_size_in_map_units_minus1						= 395;							///< For 352x288 frame. Num of map units (macroblocks for frames) in the pic. Macroblock width * height.
	/// Not initialised: _slice_group_id[7];										///< Slice group mapping.

	_num_ref_idx_l0_active_minus1						= 0;								///< Max ref index for ref pic list0.
	_num_ref_idx_l1_active_minus1						= 0;								///< Max ref index for ref pic list1. (For B-Slices)

	_weighted_pred_flag											= 0;								///< Indicates weighted prediction applied to P-Slices.
	_weighted_bipred_idc										= 0;								///< Weighted prediction type applied to B-Slices.

	_pic_init_qp_minus26										= 0;								///< Initial value of lum SliceQP - 26 for each slice. The slice_qp_delata modifies this value. Rng = [-26..25].
	_pic_init_qs_minus26										= 0;								///< For SP and SI slices.
	_chroma_qp_index_offset									= 0;								///< Offset added to lum QP (and QS) for Cb chr QP values. Rng = [-12..12].
	_second_chroma_qp_index_offset					= 0;								///< For Cr chr QP. When not present = _chroma_qp_index_offset above.
	_deblocking_filter_control_present_flag = 0;								///< Indicates presence of elements in slice header to change the characteristics of the deblocking filter.
	_constrained_intra_pred_flag						= 1;								///< = 1. Indicates that intra macroblock prediction can only be done from other intra macroblocks. 
	_redundant_pic_cnt_present_flag					= 0;								///< Indicates that redundant pic count elements are in the slice header.
	_transform_8x8_mode_flag								= 0;								///< = 0. Indicates 8x8 transform is used. When not present = 0.
	_pic_scaling_matrix_present_flag				= 0;								///< = 0. Indicates params are present to modify the scaling lists specified in the seq param sets.
	/// Not initialised:_pic_scaling_list_present_flag[8];			///< Scaling list syntax structure present for scaling list i = 0..7.

}//end constructor.

PicParamSetH264::~PicParamSetH264(void)
{
}//end destructor.

void PicParamSetH264::CopyProxy(PicParamSetH264* me, PicParamSetH264* from)
{
	me->_pic_parameter_set_id										= from->_pic_parameter_set_id;
	me->_seq_parameter_set_id										= from->_seq_parameter_set_id;

	me->_entropy_coding_mode_flag								= from->_entropy_coding_mode_flag;
	me->_pic_order_present_flag									= from->_pic_order_present_flag;

	me->_num_slice_groups_minus1								= from->_num_slice_groups_minus1;
	me->_slice_group_map_type										= from->_slice_group_map_type;
	/// Not initialised: _run_length_minus1[7];
	/// Not initialised: _top_left[7];
	/// Not initialised: _bottom_right[7];
	me->_slice_group_change_direction_flag			= from->_slice_group_change_direction_flag;
	me->_slice_group_change_rate_minus1					= from->_slice_group_change_rate_minus1;
	me->_pic_size_in_map_units_minus1						= from->_pic_size_in_map_units_minus1;
	/// Not initialised: _slice_group_id[7];

	me->_num_ref_idx_l0_active_minus1						= from->_num_ref_idx_l0_active_minus1;
	me->_num_ref_idx_l1_active_minus1						= from->_num_ref_idx_l1_active_minus1;

	me->_weighted_pred_flag											= from->_weighted_pred_flag;
	me->_weighted_bipred_idc										= from->_weighted_bipred_idc;

	me->_pic_init_qp_minus26										= from->_pic_init_qp_minus26;
	me->_pic_init_qs_minus26										= from->_pic_init_qs_minus26;
	me->_chroma_qp_index_offset									= from->_chroma_qp_index_offset;
	me->_second_chroma_qp_index_offset					= from->_second_chroma_qp_index_offset;
	me->_deblocking_filter_control_present_flag = from->_deblocking_filter_control_present_flag;
	me->_constrained_intra_pred_flag						= from->_constrained_intra_pred_flag; 
	me->_redundant_pic_cnt_present_flag					= from->_redundant_pic_cnt_present_flag;
	me->_transform_8x8_mode_flag								= from->_transform_8x8_mode_flag;
	me->_pic_scaling_matrix_present_flag				= from->_pic_scaling_matrix_present_flag;
	/// Not initialised:_pic_scaling_list_present_flag[8];
}//end CopyProxy.

int PicParamSetH264::EqualsProxy(PicParamSetH264* me, PicParamSetH264* to)
{
	if( (me->_pic_parameter_set_id							!= to->_pic_parameter_set_id)||
	    (me->_seq_parameter_set_id							!= to->_seq_parameter_set_id) )
        return(0);

	if( (me->_entropy_coding_mode_flag					!= to->_entropy_coding_mode_flag)||
	    (me->_pic_order_present_flag						!= to->_pic_order_present_flag) )
        return(0);

	if( (me->_num_slice_groups_minus1						!= to->_num_slice_groups_minus1)||
	    (me->_slice_group_map_type							!= to->_slice_group_map_type)||
	/// Not initialised: _run_length_minus1[7];
	/// Not initialised: _top_left[7];
	/// Not initialised: _bottom_right[7];
	    (me->_slice_group_change_direction_flag	!= to->_slice_group_change_direction_flag)||
	    (me->_slice_group_change_rate_minus1		!= to->_slice_group_change_rate_minus1)||
	    (me->_pic_size_in_map_units_minus1			!= to->_pic_size_in_map_units_minus1) )
	/// Not initialised: _slice_group_id[7];
        return(0);

	if( (me->_num_ref_idx_l0_active_minus1			!= to->_num_ref_idx_l0_active_minus1)||
	    (me->_num_ref_idx_l1_active_minus1			!= to->_num_ref_idx_l1_active_minus1) )
        return(0);

	if( (me->_weighted_pred_flag								!= to->_weighted_pred_flag)||
	    (me->_weighted_bipred_idc								!= to->_weighted_bipred_idc) )
        return(0);

	if( (me->_pic_init_qp_minus26								!= to->_pic_init_qp_minus26)||
	    (me->_pic_init_qs_minus26								!= to->_pic_init_qs_minus26)||
	    (me->_chroma_qp_index_offset						!= to->_chroma_qp_index_offset)||
	    (me->_second_chroma_qp_index_offset			!= to->_second_chroma_qp_index_offset)||
	    (me->_deblocking_filter_control_present_flag != to->_deblocking_filter_control_present_flag)||
	    (me->_constrained_intra_pred_flag				!= to->_constrained_intra_pred_flag)|| 
	    (me->_redundant_pic_cnt_present_flag		!= to->_redundant_pic_cnt_present_flag)||
	    (me->_transform_8x8_mode_flag						!= to->_transform_8x8_mode_flag)||
	    (me->_pic_scaling_matrix_present_flag		!= to->_pic_scaling_matrix_present_flag) )
	/// Not initialised:_pic_scaling_list_present_flag[8];
        return(0);

  return(1);
}//end EqualsProxy.
========== END FILE: CodecUtils/PicParamSetH264.cpp ==========

========== BEGIN FILE: CodecUtils/PicParamSetH264.h ==========
Bundle entry: 102
Original bytes: 5573
Original SHA-256: bc064fc169d2bb7918b2edd671c5e0adeafa59fc7341b065a4a9091fc035ef01
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: PicParamSetH264

TAG						: PPSH264

FILE NAME			: PicParamSetH264.h

DESCRIPTION		: A class to hold H.264 picture parameter set data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _PICPARAMSETH264_H
#define _PICPARAMSETH264_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class PicParamSetH264
{
public:
	PicParamSetH264(int pic_param_set_id = 0);
	virtual ~PicParamSetH264(void);

/// Public operators.
public:
  void Copy(PicParamSetH264* from) { CopyProxy(this, from); }
  int Equals(PicParamSetH264* to) { return(EqualsProxy(this, to)); }

/// Private operators.
private:
  static void CopyProxy(PicParamSetH264* me, PicParamSetH264* from);
  static int EqualsProxy(PicParamSetH264* me, PicParamSetH264* to);

/// Public constants.
public:

/// Public members.
public:
	int _pic_parameter_set_id;										///< The index for this definition of picture params [0..255].
	int _seq_parameter_set_id;										///< This pic param set refers to this seq param set. Range = [0..31].

	int _entropy_coding_mode_flag;								///< CAVLC/CABAC = 0/1.
	int _pic_order_present_flag;									///< Pic order count syntax elements are present in the slice header.

	int _num_slice_groups_minus1;									///< = 0 (baseline profile). Num of slice groups for a pic.
	int _slice_group_map_type;										///< Defines map units to slice groups. Range = [0..6].
	int _run_length_minus1[7];										///< Slice group mapping.
	int _top_left[7];															///< Slice group mapping.
	int _bottom_right[7];													///< Slice group mapping.
	int _slice_group_change_direction_flag;				///< Slice group mapping.
	int _slice_group_change_rate_minus1;					///< Slice group mapping.
	int _pic_size_in_map_units_minus1;						///< Num of map units (macroblocks for frames) in the pic. Macroblock width * height.
	int _slice_group_id[7];												///< Slice group mapping.

	int _num_ref_idx_l0_active_minus1;						///< Max ref index for ref pic list0.
	int _num_ref_idx_l1_active_minus1;						///< Max ref index for ref pic list1. (For B-Slices)

	int _weighted_pred_flag;											///< Indicates weighted prediction applied to P-Slices.
	int _weighted_bipred_idc;											///< Weighted prediction type applied to B-Slices.

	int _pic_init_qp_minus26;											///< Initial value of lum SliceQP - 26 for each slice. The slice_qp_delata modifies this value. Rng = [-26..25].
	int _pic_init_qs_minus26;											///< For SP and SI slices.
	int _chroma_qp_index_offset;									///< Offset added to lum QP (and QS) for Cb chr QP values. Rng = [-12..12].
	int _second_chroma_qp_index_offset;						///< For Cr chr QP. When not present = _chroma_qp_index_offset above.
	int _deblocking_filter_control_present_flag;	///< Indicates presence of elements in slice header to change the characteristics of the deblocking filter.
	int _constrained_intra_pred_flag;							///< = 1. Indicates that intra macroblock prediction can only be done from other intra macroblocks. 
	int _redundant_pic_cnt_present_flag;					///< Indicates that redundant pic count elements are in the slice header.
	int _transform_8x8_mode_flag;									///< = 0. Indicates 8x8 transform is used. When not present = 0.
	int _pic_scaling_matrix_present_flag;					///< = 0. Indicates params are present to modify the scaling lists specified in the seq param sets.
	int _pic_scaling_list_present_flag[8];				///< Scaling list syntax structure present for scaling list i = 1..8.

};// end class PicParamSetH264.

#endif	//_PICPARAMSETH264_H
========== END FILE: CodecUtils/PicParamSetH264.h ==========

========== BEGIN FILE: CodecUtils/PrefixH264VlcDecoderImpl1.h ==========
Bundle entry: 103
Original bytes: 3339
Original SHA-256: 83f72a84275f88c95e6440495310bf0d445673121eb2b9a08c0f19c3492ead98
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: PrefixH264VlcDecoderImpl1

TAG						: PH264VDI1

FILE NAME			: PrefixH264VlcDecoderImpl1.h

DESCRIPTION		: A class to implement a Exp-Golomb prefix Vlc decoder with 
								an IVlcDecoder interface. Trivial decoder that counts leading
								zeros.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _PREFIXH264VLCDECODERIMPL1_H
#define _PREFIXH264VLCDECODERIMPL1_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class PrefixH264VlcDecoderImpl1 : public IVlcDecoder
{
public:
	PrefixH264VlcDecoderImpl1(void)						{ _numCodeBits = 0; }
	virtual ~PrefixH264VlcDecoderImpl1(void)	{ }

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }

	/** Decode a prefix value from the stream.
	Trivial implementation of symbol number of leading zeros followed by a 1. Read 
	the codeword from the	bit stream and return it. _numCodeBits is set.
	@param bsr	: Bit stream to read from.
	@return			: The decoded symbol.
	*/
	int Decode(IBitStreamReader* bsr) 
	{ 
		int symbol = 0;
		while(0 == bsr->Read())
			symbol++;
		_numCodeBits = symbol + 1;
		return(symbol);
	}//end Decode. 

protected:
	int 	_numCodeBits;	///< Number of coded bits for the last decode.

};// end class PrefixH264VlcDecoderImpl1.

#endif	//_PREFIXH264VLCDECODERIMPL1_H
========== END FILE: CodecUtils/PrefixH264VlcDecoderImpl1.h ==========

========== BEGIN FILE: CodecUtils/PrefixH264VlcEncoderImpl1.h ==========
Bundle entry: 104
Original bytes: 3290
Original SHA-256: 2b60f830e550d8cc011f4c47d56d276228b2ff743a0e8265b589243abcf7a5a1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: PrefixH264VlcEncoderImpl1

TAG						: PH263VEI1

FILE NAME			: PrefixH264VlcEncoderImpl1.h

DESCRIPTION		: An Exp-Goulomb prefix Vlc encoder implementation with an	
								IVlcEncoder Interface. Encode is trivial.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

==========================================================================================
*/
#ifndef _PREFIXH264VLCENCODERIMPL1_H
#define _PREFIXH264VLCENCODERIMPL1_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class PrefixH264VlcEncoderImpl1 : public IVlcEncoder
{
public:
	PrefixH264VlcEncoderImpl1(void)	{ _numCodeBits = 0; _bitCode = 0; }
	virtual ~PrefixH264VlcEncoderImpl1(void)	{ }

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }

	/** Encode the prefix symbol.
	Trivial implementation of symbol number of leading zeros followed by a 1. Note that
	only symbol values up to 31 can be encoded i.e. int = 32 bits with the added 1.
	@param	symbol	: Symbol to encode.
	@return					: Num of bits.
	*/
	int Encode(int symbol) { _bitCode = 1; _numCodeBits = symbol + 1; return(_numCodeBits); }

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

};// end class PrefixH264VlcEncoderImpl1.

#endif	// end _PREFIXH264VLCENCODERIMPL1_H.
========== END FILE: CodecUtils/PrefixH264VlcEncoderImpl1.h ==========

========== BEGIN FILE: CodecUtils/RateControlImpl1.cpp ==========
Bundle entry: 105
Original bytes: 22058
Original SHA-256: de78ea5968d15ab337c0b3dd5ebda8708176b2e8d7a5d5f9c55dcbf3572a57d0
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImpl1

TAG						: RCI1

FILE NAME			: RateControlImpl1.cpp

DESCRIPTION		: A class to hold the model for the frame buffer rate rate control to
                match an average rate stream. This class models the RD curve with a
                power function.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#endif

#include "RateControlImpl1.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
int RateControlImpl1::Create(int numOfFrames)
{
  /// Clean up first.
  Destroy();

  if( (!_meanDiffSamples.Create(numOfFrames))   || (!_totalRateSamples.Create(numOfFrames))  || 
      (!_coeffRateSamples.Create(numOfFrames))  || (!_distortionSamples.Create(numOfFrames))    ||
      (!_headerRateSamples.Create(numOfFrames)) || (!_modelRateDiffSamples.Create(numOfFrames)) ) 
    return(0);

  _numOfFrames = numOfFrames; 
  _meanDiffSamples.Clear(); 
  _totalRateSamples.Clear(); 
  _coeffRateSamples.Clear(); 
  _distortionSamples.Clear();
  _headerRateSamples.Clear();
  _modelRateDiffSamples.Clear();

  _prevMeanDiff       = 0.0;
  _prevTotalRate      = 0.0;
  _prevCoeffRate      = 0.0;
  _prevDistortion     = 0.0;
  _prevHeaderRate     = 0.0;
  _prevModelRateDiff  = 0.0;
  _movingAvg          = 0.0;
  _movingAvgCount     = 1;

  _prevCoeffRatePred  = 0.0;
  _outOfBoundsFlag    = false;

  _Sx   = 0.0;
  _Sy   = 0.0;
  _Sxy  = 0.0;
  _Sx2  = 0.0;

  _SEi  = (double)(numOfFrames*(numOfFrames+1))/2.0;
  _SEi2 = (double)(numOfFrames*(numOfFrames+1)*((2*numOfFrames)+1))/6.0;
  _SEy  = 0.0;
  _SEiy = 0.0;
  _a1   = 1.0;
  _a2   = 0.0;

  _Sbuff = 0.0;

  _SPy  = 0.0;
  _SPiy = 0.0;
  _p1   = 1.0;
  _p2   = 0.0;

  _SMy  = 0.0;
  _SMiy = 0.0;
  _m1   = 1.0;
  _m2   = 0.0;

  _RCTableLen = 0;
  _RCTablePos = 0;

#ifdef RCI1_DUMP_RATECNTL
  _RCTableLen = 500;
	_RCTable.Create(11, _RCTableLen);

  _RCTable.SetHeading(0, "Frame");
  _RCTable.SetDataType(0, MeasurementTable::INT);
  _RCTable.SetHeading(1, "Dmax");
  _RCTable.SetDataType(1, MeasurementTable::INT);
  _RCTable.SetHeading(2, "Rate");
  _RCTable.SetDataType(2, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(3, "Pred Coeff Rate");
  _RCTable.SetDataType(3, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(4, "Coeff Rate");
  _RCTable.SetDataType(4, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(5, "Pred Head Rate");
  _RCTable.SetDataType(5, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(6, "Head Rate");
  _RCTable.SetDataType(6, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(7, "Pred Mean Diff");
  _RCTable.SetDataType(7, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(8, "Mean Diff");
  _RCTable.SetDataType(8, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(9, "RD a");
  _RCTable.SetDataType(9, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(10, "RD b");
  _RCTable.SetDataType(10, MeasurementTable::DOUBLE);

  _predMD           = 0.0;
  _MD               = 0.0;
  _predHeaderRate  = 0.0;
  _headerRate      = 0.0;
  _predDmax         = 0.0;
  _predCoeffRate    = 0.0;
  _coeffRate        = 0.0;
  _rate             = 0.0;
#endif

  return(1);
}//end Create.

void RateControlImpl1::Destroy(void)
{
  _RCTable.Destroy();

  _modelRateDiffSamples.Destroy();
  _headerRateSamples.Destroy(); 
  _distortionSamples.Destroy(); 
  _coeffRateSamples.Destroy(); 
  _totalRateSamples.Destroy(); 
  _meanDiffSamples.Destroy();

  _numOfFrames = 0;

}//end Destroy.

void RateControlImpl1::Reset(void)
{
  _modelRateDiffSamples.MarkAsEmpty();
  _headerRateSamples.MarkAsEmpty(); 
  _distortionSamples.MarkAsEmpty(); 
  _coeffRateSamples.MarkAsEmpty(); 
  _totalRateSamples.MarkAsEmpty(); 
  _meanDiffSamples.MarkAsEmpty();

}//end Reset.

void RateControlImpl1::Dump(const char* filename)
{
  if(_RCTablePos > 0)
    _RCTable.Save(filename, ",", 1);
  _RCTablePos = 0;
}//end Dump.

/*
---------------------------------------------------------------------------
	Public Interface Methods.
---------------------------------------------------------------------------
*/

///---------------------- Post-Encoding Measurements --------------------------

/// Add samples to the fifo buffers and hold the sample that is discarded. The
/// last discarded value is needed in the running sum update process.

/** Store model measurements after encoding a frame.
All rate measurements are in bpp.
@param rate       : Total rate of the frame including headers.
@param coeffrate  : Rate of the frame coeff encoding without headers.
@param distortion : Implementation specific distortion of the frame.
@param meandiff   : Implementation specific signal mean difference of the frame.
@return           : none.
*/
void RateControlImpl1::StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae)
{ 
  bool initialisationRequired = (bool)(!ValidData());  ///< Status prior to storing new measurement values.
  double meandiff = mse;

  /// Store all new measurements.
  PutMeanDiff(meandiff, initialisationRequired);      ///<  NB: Mean diff MUST be stored first as the others use its value.
  PutDistortion(distortion, initialisationRequired);  ///< Internally uses meandiff
  PutCoeffRate(coeffrate, initialisationRequired);
  ///< Model mismatch is difference between predicted and actual coeff rates.
  PutModelRateDiff(_prevCoeffRatePred - GetMostRecentCoeffRate(), initialisationRequired);
  PutTotalRate(rate, initialisationRequired);
  PutHeaderRate(GetMostRecentTotalRate() - GetMostRecentCoeffRate(), initialisationRequired);

  if(!initialisationRequired) ///< /// Update the running sums associated with the model. 
  { ///< ------------------ Update ----------------------------------------------
    /// Update (ln(Dmax/md), ln(r)) running sums.
    double x = (_distortionSamples.GetBuffer())[0];
    double y = (_coeffRateSamples.GetBuffer())[0];

    double x2   = x*x;
    double px2  = _prevDistortion*_prevDistortion;
    _Sx   = UpdateRunningSum(_prevDistortion, x, _Sx);
    _Sy   = UpdateRunningSum(_prevCoeffRate, y, _Sy);
    _Sxy  = UpdateRunningSum(_prevDistortion*_prevCoeffRate, x*y, _Sxy);
    _Sx2  = UpdateRunningSum(px2, x2, _Sx2);

    /// Improvements on the current parameters applied to the objective function. Find the Cramer's Rule 
    /// solution and test it against boundary conditions. If the solution is out of bounds then use a gradient
    /// decsent algorithm to modify the current parameters. Choos only those solutions that improve on the
    /// objective function.
    int si;
    /// Cramer's Solution and objective function (aa,bb) with current objective function (_a,_b)
    double bb, aa;
    CramersRuleSoln(_Sx2, _Sx, _Sx, (double)_numOfFrames, _Sxy, _Sy, &bb, &aa);
    double logaa = aa;
    aa = exp(aa);
    double loga           = log(_a);
    double currObjFunc    = 0.0;
    double cramerObjFunc  = 0.0;
    for(si = 0; si < _numOfFrames; si++)
    {
      double crs  = (_coeffRateSamples.GetBuffer())[si];
      double ds   = (_distortionSamples.GetBuffer())[si];
      double curr = crs - (_b*ds) - loga;
      currObjFunc += curr*curr;
      double cramer = crs - (bb*ds) - logaa;
      cramerObjFunc += cramer*cramer;
    }//end for si...
    /// Outside boubndary conditions.
    bool cramerDisqualified = (aa < 24.0)||(aa > 100000.0)||(bb < -3.0)||(bb > -0.3);

    /// Choose best improved solution.
    if( !cramerDisqualified && (cramerObjFunc <= currObjFunc) )
    {
      _a = aa;
      _b = bb;
    }//end if !cramerDisqualified...
    else ///< use gradient descent change if Cramer's soln is out of bounds.
    {
      /// Determine the gradient vector at current parameters (_a,_b).
      double dsdb = 2.0*((_b*_Sx2) + (log(_a)*_Sx) - _Sxy);
      double dsda = 2.0*((_b*_Sx) + (log(_a)*(double)_numOfFrames) - _Sy)/_a;
      /// Search for gamma.
      double gamma = 1.0;
      double a, b;
      double gradObjFunc = currObjFunc + 1.0;
      int cnt = 0;
      while( (cnt < 26)&&(gradObjFunc > currObjFunc) )
      {
        b = _b - (gamma * dsdb);
        a = _a - (gamma * dsda);
        loga = log(a);
        gradObjFunc = 0.0;
        for(si = 0; si < _numOfFrames; si++)
        {
          double grad = (_coeffRateSamples.GetBuffer())[si] - (b*(_distortionSamples.GetBuffer())[si]) - loga;
          gradObjFunc += grad*grad;
        }//end for si...

        gamma = gamma/2.0;
        cnt++;
      }//end while cnt...
      if(gradObjFunc <= currObjFunc)
      {
        _a = a;
        _b = b;
      }//end if gradObjFunc...
    }//end else...

    /// Update mean diff running sums.
    _SEy  = UpdateRunningSum(_prevMeanDiff, (_meanDiffSamples.GetBuffer())[0], _SEy);
    _SEiy = 0.0;
    for(int i = 0; i < _numOfFrames; i++)
      _SEiy  += (_numOfFrames-i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
    /// Update linear constants. Cramer's Rule.
    CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SEiy, _SEy, &_a1, &_a2);

    /// Update model diff running sums and moving average.
    _SMy  = UpdateRunningSum(_prevModelRateDiff, (_modelRateDiffSamples.GetBuffer())[0], _SMy);
    _SMiy = 0.0;
    for(int i = 0; i < _numOfFrames; i++)
      _SMiy  += (_numOfFrames-i)*(_modelRateDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
    /// Update linear constants. Cramer's Rule.
    CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SMiy, _SMy, &_m1, &_m2);
    _movingAvgCount++;
    if(_movingAvgCount > (1000 * _numOfFrames))   ///< Long term reset.
      _movingAvgCount = 1;    ///< Reset and leave the current moving avg unchanged.
    else
      _movingAvg = ((_modelRateDiffSamples.GetBuffer())[0] + ((double)(_movingAvgCount-1) * _movingAvg))/(double)_movingAvgCount;

    /// Update total rate running sums.
    _Sbuff = UpdateRunningSum(_prevTotalRate, (_totalRateSamples.GetBuffer())[0], _Sbuff);

    /// Update header rate running sums.
    _SPy  = UpdateRunningSum(_prevHeaderRate, (_headerRateSamples.GetBuffer())[0], _SPy);
    _SPiy = 0.0;
    for(int i = 0; i < _numOfFrames; i++)
      _SPiy  += (_numOfFrames-i)*(_headerRateSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
    /// Update header rate linear constants. Cramer's Rule.
    CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SPiy, _SPy, &_p1, &_p2);

  }//end if !initialisationRequired...
  else  ///< Indicates that there was no valid data in the model before storing these first samples.
  { ///< ------------------ Initialise ----------------------------------------------
    /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
    _Sx   = 0;
    _Sy   = 0;
    _Sxy  = 0;    ///< Power R-D.
    _Sx2  = 0;

    _SEy  = 0.0;  ///< Linear Mean Diff
    _SEiy = 0.0;

    _SMy  = 0.0;  ///< Linear Model Diff
    _SMiy = 0.0;

    _Sbuff = 0.0; ///< Frame bit buffer.

    _SPy  = 0.0;  ///< Linear header rate
    _SPiy = 0.0;

    for(int i = 0; i < _numOfFrames; i++)
    {
      ///< Power R-D.
      double x = (_distortionSamples.GetBuffer())[i];
      double y = (_coeffRateSamples.GetBuffer())[i];

      double x2 = x*x;
      _Sx   += x;
      _Sy   += y;
      _Sxy  += x*y;
      _Sx2  += x2;

      ///< Linear Mean Diff
      x = (_meanDiffSamples.GetBuffer())[i];
      /// _SEi and _SEi2 are constants.
      _SEy   += x;
      /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
      /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
      /// from the last frame. Extrapolation will predict x[N+1].
      _SEiy  += (_numOfFrames-i)*x; ///< The sample time series are in reverse order in the fifo.

      ///< Linear Model Diff
      y = (_modelRateDiffSamples.GetBuffer())[i];
      /// _SEi and _SEi2 are constants.
      _SMy   += y;
      _SMiy  += (_numOfFrames-i)*y; ///< The sample time series are in reverse order in the fifo.
      _movingAvg = (_modelRateDiffSamples.GetBuffer())[0];
      _movingAvgCount = 1;

      /// Frame bit buffer.
      _Sbuff += (_totalRateSamples.GetBuffer())[i];

      /// Header rate.
      x = (_headerRateSamples.GetBuffer())[i];
      /// _SEi and _SEi2 are constants.
      _SPy   += x;
      /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
      /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
      /// from the last frame. Extrapolation will predict x[N+1].
      _SPiy  += (_numOfFrames-i)*x; ///< The sample time series are in reverse order in the fifo.

    }//end for i...

  }//end else...

#ifdef RCI1_DUMP_RATECNTL
  _MD           = GetMostRecentMeanDiff();
  _coeffRate    = GetMostRecentCoeffRate();
  _rate         = GetMostRecentTotalRate();
  _headerRate   = GetMostRecentHeaderRate();

  /// This method is the last to be called after processing a frame. Therefore dump here.
  if(_RCTablePos < _RCTableLen)
  {
    _RCTable.WriteItem(0, _RCTablePos, _RCTablePos);  ///< P-Frame
    _RCTable.WriteItem(1, _RCTablePos, (int)(0.5 + _predDmax)); ///< Dmax
    _RCTable.WriteItem(2, _RCTablePos, _rate);  ///< Rate
    _RCTable.WriteItem(3, _RCTablePos, _predCoeffRate);  ///< Pred Coeff Rate
    _RCTable.WriteItem(4, _RCTablePos, _coeffRate);  ///< Coeff Rate
    _RCTable.WriteItem(5, _RCTablePos, _predHeaderRate);  ///< Pred Head Rate
    _RCTable.WriteItem(6, _RCTablePos, _headerRate);  ///< Head Rate
    _RCTable.WriteItem(7, _RCTablePos, _predMD);  ///< Pred Mean Diff
    _RCTable.WriteItem(8, _RCTablePos, _MD);  ///< Mean Diff
    _RCTable.WriteItem(9, _RCTablePos, _a);  ///< Model parameter a
    _RCTable.WriteItem(10, _RCTablePos, _b);  ///< Model parameter b

    _RCTablePos++;
  }//end if _RCTablePos... 
#endif

}//end StoreMeasurements.

///---------------------- Pre-Encoding Predictions --------------------------

/** Predict the distortion for the next frame from the desired average rate.
The distortion measure is predicted from the coeff rate (total rate - header rate) using
an appropriate R-D model. The header rate and the signal mean diff are predicted from the
previous measured frame data using linear extrapolation.
@param  targetAvgRate : Total targeted average rate (including headers).
@param  rateLimit     : Upper limit to predicted rate.
@return               : Predicted distortion.
*/
int RateControlImpl1::PredictDistortion(double targetAvgRate, double rateLimit)
{
//  const double minRate  = 0.001;
  const double minRate  = 0.0001;
  _outOfBoundsFlag      = false;

  /// Default settings for the non-valid data case.
  double targetCoeffRate      = targetAvgRate;
  double targetCoeffRateLimit = rateLimit;
  double predHeaderRate       = 0.02;

  ///------------------ Rate Prediction --------------------------------------
  if(ValidData())
  {
    /// Buffer averaging model: What must the target rate for the
    /// next N frames be to make the average over the rate buffer equal
    /// to the average target rate specified in the parameter?
//    double avgBuffRate = _Sbuff/(double)_numOfFrames;
    /// Define target rate = (1 + 1/N)*target avg rate - (buff rate/N).
//    double targetRate  = ((1.0 + (1.0/(double)_numOfFrames))*targetAvgRate) - (avgBuffRate/(double)_numOfFrames); ///< ...with headers.
//    double targetRate  = (2.0*targetAvgRate) - (_Sbuff/(double)_numOfFrames); ///< ...with headers.

    /// N past frames and recover in k frames: target rate = target avg rate*(N+k)/k - total buff/k.
    int numRecoverFrames = _numOfFrames;
    double targetRate = ((targetAvgRate * (double)(_numOfFrames + numRecoverFrames))/(double)numRecoverFrames) - (_Sbuff/(double)numRecoverFrames);

/////////////////////////////////////////////////////////////////////////
    targetCoeffRate = targetRate;
/////////////////////////////////////////////////////////////////////////
/*
    /// Check that the result is reasonable. If not then force it to some arbitrary minimum.
    if(targetRate < 0.0)  
      targetRate = (_headerRateSamples.GetBuffer())[0] + minRate;

    /// Predict the header rate with linear extrapolation model.
    predHeaderRate = (_p1*(double)(_numOfFrames+1)) + _p2;
     /// Check that the result is reasonable. If not, use the last entry.
    if( (predHeaderRate > targetAvgRate) || (predHeaderRate < 0.0) ) 
      predHeaderRate = (_headerRateSamples.GetBuffer())[0];          

    /// Remove the header rate to predict the coeff rate.
    targetCoeffRate = targetRate - predHeaderRate;
    targetCoeffRateLimit = rateLimit - predHeaderRate;

    /// Predict model mismatch diff with the active mismatch function.
    double mismatchPred;
    if(_modelMismatchType == LINEAR)  ///< Linear extrapolation model.
      mismatchPred = (_m1*(double)(_numOfFrames+1)) + _m2;
    else if(_modelMismatchType == CONSTANT)  ///< Moving average model (converging to a constant).
      mismatchPred = _movingAvg;
    else ///< if(_modelMismatchType == NONE)
      mismatchPred = 0.0;

    /// Only small mismatches are permitted otherwise it is asuumed that
    /// the mismatch prediction has not yet converged and is ignored.
//    if( abs(mismatchPred) < abs(0.8 * targetCoeffRate) )   ///< %
      targetCoeffRate = targetCoeffRate + mismatchPred;
*/
  }//end if ValidData...
/*
  else  ///< There is no valid data in the fifo buffers yet.
  {
    if(targetAvgRate > 0.02) ///< Guess header rate at 0.02 bpp.
      targetCoeffRate = targetAvgRate - 0.02;
  }//end else...
*/
  /// Keep the target rate within the upper rate limit.
  if(targetCoeffRate > targetCoeffRateLimit)
    targetCoeffRate = targetCoeffRateLimit;

  /// No less than the coeff floor rate.
  if(targetCoeffRate < 0.00)
    targetCoeffRate = minRate;
  _prevCoeffRatePred = targetCoeffRate;

  ///--------------- Distortion Prediction -----------------------------------------

  /// Predict Mean Diff with linear extrapolation model.
  double predMD = (_a1*(double)(_numOfFrames+1)) + _a2;
  /// Can never be negative. Use last value if prediction is negative.
  if(predMD < 0.0)
    predMD = (_meanDiffSamples.GetBuffer())[0]; ///< Mean diff samples are in reverse order.

//  double lastDist = (_meanDiffSamples.GetBuffer())[0]*exp((_distortionSamples.GetBuffer())[0]);

  double distd = predMD*exp((log(targetCoeffRate/_a))/_b);
/*
  /// Do not let Dmax change by more than 50% from frame to frame.
  double changeFraction = (abs(distd - lastDist))/lastDist;
  if(changeFraction > 0.5)  ///< 50%
  {
    if(distd > lastDist)
      distd = lastDist*1.5;
    else
      distd = lastDist*0.5;
    _outOfBoundsFlag = true;
  }//end if changeFraction...
*/
  /// Cannot be greater than 16x16x(256^2)
  if(distd > 16777216.0)
  {
    distd = 16777216.0;
    _outOfBoundsFlag = true;
  }//end if distd...
  /// Cannot be less than 16x16x(2^2)
  if(distd < 1024.0)
  {
    distd = 1024.0;
    _outOfBoundsFlag = true;
  }//end if distd...

  /// Update the target coeff rate with changes in Dmax boundaries.
  if(_outOfBoundsFlag)
  {
    targetCoeffRate = _a*pow((distd/predMD), _b);
    _prevCoeffRatePred = targetCoeffRate;
  }//end if _outOfBoundsFlag...

#ifdef RCI1_DUMP_RATECNTL
  _predHeaderRate   = predHeaderRate;
  _predCoeffRate    = targetCoeffRate;
  _predMD           = predMD;
  _predDmax         = distd;
#endif

  return((int)(distd + 0.5));
}//end PredictDistortion.

========== END FILE: CodecUtils/RateControlImpl1.cpp ==========

========== BEGIN FILE: CodecUtils/RateControlImpl1.h ==========
Bundle entry: 106
Original bytes: 9971
Original SHA-256: 0638c4192c1984ef4960c6263a6c49593246e1aa307b0606aa6d29b77ef5a068
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImpl1

TAG						: RCI1

FILE NAME			: RateControlImpl1.h

DESCRIPTION		: A class to hold the model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RATECONTROLIMPL1_H
#define _RATECONTROLIMPL1_H


#pragma once

#include  <math.h>
#include  "Fifo.h"
#include  "IRateControl.h"
#include  "MeasurementTable.h"

//#define RCI1_DUMP_RATECNTL  1

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RateControlImpl1 : public IRateControl
{
public:
  RateControlImpl1(void) { _a = 15000.0; _b = -1.3; _numOfFrames = 0; _modelMismatchType = RateControlImpl1::NONE; }
  RateControlImpl1(double modelparam_a, double modelparam_b, int modelmismatchtype) { _a = modelparam_a; _b = modelparam_b; _numOfFrames = 0; _modelMismatchType = modelmismatchtype; }
  virtual ~RateControlImpl1() { Destroy(); }

// Setup and interface methods.
public:
  int		Create(int numOfFrames);
  void	Destroy(void);
  int   GetFameBufferLength(void) { return(_numOfFrames); }
  void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) {}

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target coeff rate.
  int PredictDistortion(double targetAvgRate, double rateLimit);
  /// Post-encoding: Add samples to the fifo buffers and hold the sample that is discarded.
  void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae);

  /// Return average rate across the buffer as the performance measure.
  double GetPerformanceMeasure(void) { return(_Sbuff/(double)_numOfFrames); }
  /// Is the data in the fifos valid.
  int ValidData(void) 
    { if(!_distortionSamples.Empty() && !_coeffRateSamples.Empty() && !_meanDiffSamples.Empty() && !_totalRateSamples.Empty() && !_headerRateSamples.Empty()) return(1); return(0); }
  /// Was the prediction calculation out of bounds?
  bool OutOfBounds(void) { return(_outOfBoundsFlag); }
  /// Reset the fifos. Use after a change in frame type.
  void Reset(void);

  /// Utility functions.
  void Dump(const char* filename);  ///< Requires RCI1_DUMP_RATECNTL to be set.

/// Further implementation specific public methods.
public:
  /// Set the function type to use for model mismatch.
  void SetModelMismatchFunc(const int funcType) { _modelMismatchType = funcType; }

/// Private methods.
protected:
  /// These following group of methods must be called in this exact order because they operate
  /// on members that are interdependant.
  void PutMeanDiff(double meandiff, bool initialise) 
    { if(meandiff < 1.0) meandiff = 1.0;
      PutLinearMeasure(_meanDiffSamples, meandiff, &_prevMeanDiff, initialise); }
  void PutDistortion(double distortion, bool initialise) ///< Must only be called after a call to PutMeanDiff(). 
    { if(distortion < 1.0) distortion = 1.0;
      PutLogMeasure(_distortionSamples, (distortion/(_meanDiffSamples.GetBuffer())[0]), &_prevDistortion, initialise); }
  void PutCoeffRate(double rate, bool initialise) 
    { PutLogMeasure(_coeffRateSamples, rate, &_prevCoeffRate, initialise); } 
  void PutModelRateDiff(double ratediff, bool initialise) 
    { PutLinearMeasure(_modelRateDiffSamples, ratediff, &_prevModelRateDiff, initialise); }
  void PutTotalRate(double rate, bool initialise) 
    { PutLinearMeasure(_totalRateSamples, rate, &_prevTotalRate, initialise); }
  void PutHeaderRate(double headerRate, bool initialise) 
    { PutLinearMeasure(_headerRateSamples, headerRate, &_prevHeaderRate, initialise); }

  double UpdateRunningSum(double prev, double curr, double currSum) { double newSum = currSum - prev; newSum += curr; return(newSum); }

  void PutLogMeasure(Fifo& samples, double m, double* prev, bool initialise)
    { if(m <= 0.0) m = 0.0001; 
      if(!initialise) *prev = samples.GetFirstOut(); else *prev = log(m); 
      samples.AddFirstIn(log(m)); }

  void PutLinearMeasure(Fifo& samples, double m, double* prev, bool initialise) 
    { if(!initialise) *prev = samples.GetFirstOut(); else *prev = m; 
      samples.AddFirstIn(m); }

  /// Solve in 2 variables returning soln in (x0, x1). If the determinant = 0 then leave (x0, x1) unchanged.
  void CramersRuleSoln(double a00, double a01, double a10, double a11, double b0, double b1, double* x0, double* x1)
  { double D = (a00 * a11)-(a10 * a01);
    if(D != 0.0) { *x0 = ((b0 * a11)-(b1 * a01))/D; *x1 = ((a00 * b1)-(a10 * b0))/D; }  }

  double GetMostRecentCoeffRate(void) { return(exp((_coeffRateSamples.GetBuffer())[0])); }
  double GetMostRecentTotalRate(void) { return((_totalRateSamples.GetBuffer())[0]); }
  double GetMostRecentHeaderRate(void) { return((_headerRateSamples.GetBuffer())[0]); }
  double GetMostRecentMeanDiff(void) { return((_meanDiffSamples.GetBuffer())[0]); }
  double GetMostRecentModelRateDiff(void) { return((_modelRateDiffSamples.GetBuffer())[0]); }

/// Constant members.
public:
  /// Model mismatch type.
  static const int NONE     = 0;
  static const int CONSTANT = 1;
  static const int LINEAR   = 2;

/// Common members.
protected:
	int				_numOfFrames;

  Fifo      _meanDiffSamples;      ///< Mean differnce between samples of frames.
  double    _prevMeanDiff;
  Fifo      _totalRateSamples;     ///< Stream rate including headers of frames.
  double    _prevTotalRate;
  Fifo      _coeffRateSamples;     ///< Coeff rate of frames.
  double    _prevCoeffRate;
  Fifo      _distortionSamples;    ///< Dmax for the frames.
  double    _prevDistortion;
  Fifo      _headerRateSamples;    ///< Header rate of frames.
  double    _prevHeaderRate;
  Fifo      _modelRateDiffSamples; ///< Model mismatch of frames.
  double    _prevModelRateDiff;
  double    _prevCoeffRatePred;
  /// Signal when the predicted values are not valid due to out of range errors. Use
  /// this signal to prevent contributions to the model data.
  bool      _outOfBoundsFlag;

  /// The model mismatch can be selected.
  int       _modelMismatchType;
  double    _movingAvg; ///< For the CONSTANT mismatch type a cumulative moving average is used.
  int       _movingAvgCount;

  /// For the quadratic model x = 1/Dmax and y = R. To update the constants
  /// c1 and c2, Cramer's Rule is used to solve the linear equation for a least
  /// mean squares criterion curve fit. Running sums are used.
  double    _Sxy;
  double    _Sx2;

  double    _Sx;
  double    _Sy;
  double    _a; ///< Power model constants.
  double    _b;

  /// The prediction of Mean Diff requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants a1 and a2.
  double    _SEi;
  double    _SEi2;
  double    _SEy;
  double    _SEiy;
  double    _a1;  ///< Linear model constants.
  double    _a2;

  /// Buffer rate control for average bit rate.
  double    _Sbuff;

  /// The prediction of frame header rate requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants p1 and p2. Uses _SEi and _SEi2 above.
  double    _SPy;
  double    _SPiy;
  double    _p1;  ///< Linear model constants.
  double    _p2;

  /// The prediction of model mismatch in rate requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants m1 and m2. Uses _SEi and _SEi2 above.
  double    _SMy;
  double    _SMiy;
  double    _m1;  ///< Linear model constants.
  double    _m2;

  MeasurementTable  _RCTable;
  int               _RCTableLen;
  int               _RCTablePos;
#ifdef RCI1_DUMP_RATECNTL
  double            _predMD;
  double            _MD;
  double            _predHeaderRate;
  double            _headerRate;
  double            _predDmax;
  double            _predCoeffRate;
  double            _coeffRate;
  double            _rate;
#endif
};// end class RateControlImpl1.

#endif	// _RATECONTROLIMPL1_H
========== END FILE: CodecUtils/RateControlImpl1.h ==========

========== BEGIN FILE: CodecUtils/RateControlImplLog.cpp ==========
Bundle entry: 107
Original bytes: 23366
Original SHA-256: a7e6ba2fca1cd618c901796c59cd83a3d48ac13dc9dcff3073918bc5682f4943
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE			  : RateControlImplLog

TAG				    : RCIL

FILE NAME		  : RateControlImplLog.cpp

DESCRIPTION		: A class to hold a natural log function  model for the frame buffer rate rate control to
				      match an average rate stream.

COPYRIGHT		  : (c)CSIR 2007-2016 all rights resevered

LICENSE			  : Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#endif

#include <sstream>
#include <stdlib.h>
#include <string.h>
#include "RateControlImplLog.h"

/*
---------------------------------------------------------------------------
Constants
---------------------------------------------------------------------------
*/
#define RCIL_NUM_SHORT_TERM_SAMPLES 4

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
int RateControlImplLog::Create(int numOfFrames)
{
  /// Clean up first.
  Destroy();

  if( (!_meanDiffSamples.Create(numOfFrames))       || (!_modelRateSamples.Create(numOfFrames))  || 
      (!_buffRateSamples.Create(numOfFrames))       || (!_distortionSamples.Create(numOfFrames)) ||
      (!_modelPredRateSamples.Create(numOfFrames))  ||  (!_modelMismatchRateSamples.Create(numOfFrames)) ) 
    return(0);

  _numOfFrames = numOfFrames; 
  _meanDiffSamples.Clear(); 
  _modelRateSamples.Clear(); 
  _buffRateSamples.Clear(); 
  _distortionSamples.Clear();
  _modelPredRateSamples.Clear();
  _modelMismatchRateSamples.Clear();

  _prevMeanDiff           = 0.0;
  _prevModelRate          = 0.0;
  _prevBuffRate           = 0.0;
  _prevDistortion         = 0.0;
  _prevModelPredRate      = 0.0;
  _prevModelMismatchRate  = 0.0;

  _outOfBoundsFlag    = false;

  _modelFit = 0.0;
  _Spr      = 0.0;
  _Smr      = 0.0;

  _Sx   = 0.0;
  _Sy   = 0.0;
  _Sxy  = 0.0;
  _Sx2  = 0.0;

  /// Long term
  _SEi    = (double)(numOfFrames*(numOfFrames+1))/2.0;
  _SEi2   = (double)(numOfFrames*(numOfFrames+1)*((2*numOfFrames)+1))/6.0;
  _SEy    = 0.0;
  _SEiy   = 0.0;
  _a1     = 1.0;
  _a2     = 0.0;
  _R2     = 1.0;
  /// Short term
  _SEi_s  = (double)(RCIL_NUM_SHORT_TERM_SAMPLES*(RCIL_NUM_SHORT_TERM_SAMPLES + 1)) / 2.0;
  _SEi2_s = (double)(RCIL_NUM_SHORT_TERM_SAMPLES*(RCIL_NUM_SHORT_TERM_SAMPLES + 1)*((2 * RCIL_NUM_SHORT_TERM_SAMPLES) + 1)) / 6.0;
  _SEy_s  = 0.0;
  _SEiy_s = 0.0;
  _a1_s   = 1.0;
  _a2_s   = 0.0;
  _R2_s   = 1.0;

  _Sbuff = 0.0;

  _mseSignal = 0.0;

  _RCTableLen = 0;
  _RCTablePos = 0;

#ifdef RCIL_DUMP_RATECNTL
  _RCTableLen = 300;
	_RCTable.Create(40, _RCTableLen);

  _RCTable.SetHeading(0, "Frame");
  _RCTable.SetDataType(0, MeasurementTable::INT);
  _RCTable.SetHeading(1, "Dmax");
  _RCTable.SetDataType(1, MeasurementTable::INT);
  _RCTable.SetHeading(2, "r Rate"); ///< Required rate
  _RCTable.SetDataType(2, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(3, "Rate"); ///< Actual rate
  _RCTable.SetDataType(3, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(4, "p MSE");  ///< Predicted MSE
  _RCTable.SetDataType(4, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(5, "MSE");  ///< Actual MSE
  _RCTable.SetDataType(5, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(6, "a");
  _RCTable.SetDataType(6, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(7, "b");
  _RCTable.SetDataType(7, MeasurementTable::DOUBLE);

  int i;
  char charBuffer[8];
  for(i = 0; i < 16; i++)
  {
    _RCTable.SetHeading(i+8, (const char*)_itoa(i, charBuffer, 10) );
    _RCTable.SetDataType(i+8, MeasurementTable::DOUBLE);
    _RCTable.SetHeading(i+24, (const char*)_itoa(i, charBuffer, 10) );
    _RCTable.SetDataType(i+24, MeasurementTable::DOUBLE);
  }//end for i...

  _predMD           = 0.0;
  _MD               = 0.0;
  _predDmax         = 0.0;
  _predRate         = 0.0;
  _rate             = 0.0;
#endif

  return(1);
}//end Create.

void RateControlImplLog::Destroy(void)
{
  _RCTable.Destroy();
  _RCTableLen = 0;
  _RCTablePos = 0;

  _modelMismatchRateSamples.Destroy(); 
  _modelPredRateSamples.Destroy(); 
  _distortionSamples.Destroy(); 
  _modelRateSamples.Destroy(); 
  _buffRateSamples.Destroy(); 
  _meanDiffSamples.Destroy();

  _numOfFrames = 0;

}//end Destroy.

void RateControlImplLog::Dump(const char* filename)
{
  if(_RCTablePos > 0)
    _RCTable.Save(filename, ",", 1);
  _RCTablePos = 0;
}//end Dump.

void RateControlImplLog::Dump(void)
{
  std::ostringstream filename;
  filename << RCIL_DUMP_FILENAME;  ///< Head.
  filename << ".csv";              ///< Tail
  Dump(filename.str().c_str());
}//end Dump.

/*
---------------------------------------------------------------------------
	Public Interface Methods.
---------------------------------------------------------------------------
*/

///---------------------- Post-Encoding Measurements --------------------------

/// Add samples to the fifo buffers and hold the sample that is discarded. The
/// last discarded value is needed in the running sum update process.

/** Store model measurements after encoding a frame.
All rate measurements are in bpp.
@param rate       : Total rate of the frame including headers.
@param coeffrate  : Not used in this implementation.
@param distortion : Implementation specific distortion of the frame.
@param mse        : Implementation specific signal mean square error of the frame.
@param mae        : Implementation specific signal mean absolute error of the frame.
@return           : none.
*/
void RateControlImplLog::StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae)
{ 
  bool initialisationRequired = (bool)(!ValidData());  ///< Status prior to storing new measurement values.

#ifdef RCIL_DUMP_RATECNTL
  _MD   = mse;
  _rate = rate;

  /// This method is the last to be called after processing a frame. Therefore dump here prior to updating the params.
  if(_RCTablePos < _RCTableLen)
  {
    _RCTable.WriteItem(0, _RCTablePos, _RCTablePos);            ///< Frame
    _RCTable.WriteItem(1, _RCTablePos, (int)(0.5 + _predDmax)); ///< Dmax
    _RCTable.WriteItem(2, _RCTablePos, _predRate);              ///< Required Rate
    _RCTable.WriteItem(3, _RCTablePos, rate);                   ///< Actual Rate
    _RCTable.WriteItem(4, _RCTablePos, _predMD);                ///< Pred MSE
    _RCTable.WriteItem(5, _RCTablePos, mse);                    ///< Actual MSE
    _RCTable.WriteItem(6, _RCTablePos, _a);                     ///< Model parameter a
    _RCTable.WriteItem(7, _RCTablePos, _b);                     ///< Model parameter b

    /// These data points were used to find _a and _b used in the prediction.
    for(int ti = 0; ti < 16; ti++)
    {
      _RCTable.WriteItem(ti+8, _RCTablePos, (_distortionSamples.GetBuffer())[ti]);  ///< Model ln(mse/dmax) data points
      _RCTable.WriteItem(ti+24, _RCTablePos, (_modelRateSamples.GetBuffer())[ti]);  ///< Model rate data points points
    }//end for i...

    _RCTablePos++;
  }//end if _RCTablePos... 
#endif

  /// Store all new measurements. Do not add to the model data if the data are out of bounds.
  PutMeanDiff(mse, initialisationRequired);           ///<  NB: Mean diff MUST be stored first as the others use its value.
  PutDistortion(distortion, initialisationRequired);  ///< Internally uses meandiff
  PutModelRate(rate, initialisationRequired);
  PutBuffRate(rate, initialisationRequired);
  PutPredRate(rate, initialisationRequired);          ///< Both the predicted rate and the mismatch rate.

  if(!initialisationRequired) ///< Update the running sums associated with the model. 
    ModelUpdate();
  else  ///< Indicates that there was no valid data in the model before storing these first samples.
    /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
    ModelInitialise();

}//end StoreMeasurements.

///---------------------- Pre-Encoding Predictions --------------------------

/** Predict the distortion for the next frame from the desired average rate.
The distortion measure is predicted from the coeff rate (total rate - header rate) using
an appropriate R-D model. The header rate and the signal mean diff are predicted from the
previous measured frame data using linear extrapolation.
@param  targetAvgRate : Total targeted average rate (including headers).
@param  rateLimit     : Upper limit to predicted rate.
@return               : Predicted distortion.
*/
int RateControlImplLog::PredictDistortion(double targetAvgRate, double rateLimit)
{
  _outOfBoundsFlag              = false;
  _upperDistortionOverflowFlag  = false;
  _lowerDistortionOverflowFlag  = false;
  _upperRateOverflowFlag        = false;
  _lowerRateOverflowFlag        = false;

  /// Default settings for the non-valid data case.
  double targetRate      = targetAvgRate;
  double targetRateLimit = rateLimit;

  ///------------------ Rate Prediction --------------------------------------
  if(ValidData())
  {
    /// Buffer averaging model: What must the target rate for the
    /// next N frames be to make the average over the rate buffer equal
    /// to the average target rate specified in the parameter?

    /// N past frames and recover in k frames: target rate = target avg rate*(N+k)/k - total buff/k.
    int numRecoverFrames = _numOfFrames;  ///< Make recovery same as past num of frames until further notice.
    targetRate = ((targetAvgRate * (double)(_numOfFrames + numRecoverFrames))/(double)numRecoverFrames) - (_Sbuff/(double)numRecoverFrames);

  }//end if ValidData...

  /// Keep the target rate within the upper rate limit.
  if(targetRate > targetRateLimit)
    targetRate = targetRateLimit;

  /// No less than the coeff floor rate.
  if(targetRate < 0.00)
    targetRate = _rateLower;

  ///--------------- Distortion Prediction -----------------------------------------

  /// Predict Mean Diff with linear extrapolation model. Select between a long term or
  /// short term prediction based on the best statistical R^2 fit with the model. Override
  /// the prediction if a scene change was signalled externally.
  double predMD = ModelMeanDifference();

  /// Model function solved for distortion.
  double distd = ModelDistortion(targetRate, _a, _b, predMD);

  /// Limit a decrease change in distortion (implying limiting an increase in rate) to 25% of previous distortion.
  double prevd = (_meanDiffSamples.GetBuffer())[0]/(exp((_distortionSamples.GetBuffer())[0]));
  double limit = prevd - (0.25*prevd);
  if((distd < limit)&&(prevd < _distUpper))
  {
    distd = limit;
    targetRate = ModelRate(distd, _a, _b, predMD);
  }//end if distd...

  /// Cannot be greater than 16x16x(256^2). In response, converge
  /// towards the upper distortion limit by halving from the previous 
  /// frame distortion.
  if(distd > _distUpper)
  {
    distd = prevd + (abs(_distUpper - prevd)*0.5);
    _outOfBoundsFlag = true;
    _upperDistortionOverflowFlag = true;
  }//end if distd...
  /// Cannot be less than 16x16x(2^2). Converge to lower distortion limit.
  if(distd < _distLower)
  {
    distd = prevd - (abs(prevd - _distLower)*0.5);
    _outOfBoundsFlag = true;
    _lowerDistortionOverflowFlag = true;
  }//end if distd...

  /// Update the target rate with changes in Dmax boundaries.
  if(_outOfBoundsFlag)
    targetRate = ModelRate(distd, _a, _b, predMD);

#ifdef RCIL_DUMP_RATECNTL
  _predRate = targetRate;
  _predMD   = predMD;
  _predDmax = distd;
#endif

  return((int)(distd + 0.5));
}//end PredictDistortion.

/*
----------------------------------------------------------------------------------------------------
  Private Methods
----------------------------------------------------------------------------------------------------
*/

/** Calculate R^2 from a sample list.
Determine the R^2 statistical model fit within an array of samples. Only
calculate for the length specified from the list and do it in reverse order.
@param  samples : Sample list of values
@param  length  : Length from the value list to use.
@param  mlin    : Linear model slope.
@param  clin    : Linear model y-intercept.
@return         : R^2.
*/
double RateControlImplLog::RSqrLinRevOrder(double* samples, int length, double mlin, double clin)
{
  double mean = 0.0;
  for (int i = 0; i < length; i++)
    mean += samples[i];
  mean = mean / length;

  double SStot = 0.0;
  double SSres = 0.0;
  for (int i = 0; i < length; i++)
  {
    double x = samples[i];
    SStot += (x - mean)*(x - mean);
    SSres += (x - (mlin*(length - i) + clin))*(x - (mlin*(length - i) + clin));
  }//end for i...

  double R2 = 1.0;
  if (SStot != 0.0)
    R2 = 1.0 - (SSres / SStot);

  return(R2);
}//end RSqrLinRevOrder.

/** Predict the mean difference between pels in the frame.
Predict the frame Mean Diff with linear extrapolation model. Select between a long term or
short term prediction based on the best statistical R^2 fit with the model. Override the 
prediction if a scene change was signalled externally and reset the signal to zero.
@return : Predicted mean difference.
*/
double RateControlImplLog::ModelMeanDifference(void)
{
  double predMD;
  if (_mseSignal == 0.0)
  {
    if (_R2_s > _R2)  ///< Short term is closer to 1.0 than the long term (better fit).
      predMD = (_a1_s*(double)(RCIL_NUM_SHORT_TERM_SAMPLES + 1)) + _a2_s; ///< Mean diff samples are in reverse order.
    else
      predMD = (_a1*(double)(_numOfFrames + 1)) + _a2;
    /// Can never be negative. Use last value if prediction is negative.
    if (predMD < 0.0)
      predMD = (_meanDiffSamples.GetBuffer())[0]; 
  }//end if _mseSignal...
  else
  {
    predMD = _mseSignal;
    _mseSignal = 0.0;  ///< Clear the signal.
  }//end else...

  return(predMD);
}//end ModelMeanDifference.

/** Initialise all R-D model buffers and persistant member variables.
Initialise the fifo buffers for the R-D model, Mean Diff and Model prediction members. The 
fifo buffers must have some valid data in them and the model parameters must be reset prior 
to calling this method. The values that are updated on every StoreMeasurement() call are
initialised here.
@return : None.
*/
void RateControlImplLog::ModelInitialise(void)
{
  _Sx   = 0;
  _Sy   = 0;
  _Sxy  = 0;    ///< Log R-D.
  _Sx2  = 0;

  _modelFit = 0.0;  ///< Performance measures.
  _Spr      = 0.0;
  _Smr      = 0.0;

  _SEy    = 0.0;  ///< Linear Mean Diff
  _SEiy   = 0.0;
  _SEy_s  = 0.0;
  _SEiy_s = 0.0;

  _Sbuff = 0.0; ///< Frame bit buffer.

  for (int i = 0; i < _numOfFrames; i++)
  {
    ///< Log R-D.
    double x = (_distortionSamples.GetBuffer())[i];
    double y = (_modelRateSamples.GetBuffer())[i];

    double x2 = x*x;
    _Sx += x;
    _Sy += y;
    _Sxy += x*y;
    _Sx2 += x2;

    _Spr += (_modelPredRateSamples.GetBuffer())[i];
    _Smr += (_modelMismatchRateSamples.GetBuffer())[i];

    ///< Linear Mean Diff
    x = (_meanDiffSamples.GetBuffer())[i];
    /// _SEi and _SEi2 are constants.
    _SEy += x;
    /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
    /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
    /// from the last frame. Extrapolation will predict x[N+1].
    _SEiy += (_numOfFrames - i)*x; ///< The sample time series are in reverse order in the fifo.

    /// Frame bit buffer rate. 
    _Sbuff += (_buffRateSamples.GetBuffer())[i];

  }//end for i...
   /// Long term R sqr.
  _R2 = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), _numOfFrames, _a1, _a2);

  for (int i = 0; i < RCIL_NUM_SHORT_TERM_SAMPLES; i++)
  {
    double x = (_meanDiffSamples.GetBuffer())[i];
    _SEy_s += x;
    _SEiy_s += (RCIL_NUM_SHORT_TERM_SAMPLES - i)*x;
  }//end for i...
   /// Short term R sqr.
  _R2_s = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), RCIL_NUM_SHORT_TERM_SAMPLES, _a1_s, _a2_s);

}//end ModelInitialise.

/** Update all R-D model parameters.
Update the model parameters for the R-D model (ln(md/Dmax), r), Mean Diff and the running 
sums. The latest data must have been loaded into the fifo buffers prior to calling this 
method. The values are updated on every StoreMeasurement() call.
@return : None.
*/
void RateControlImplLog::ModelUpdate(void)
{
  /// Update (ln(md/Dmax), r) running sums.
  double x = (_distortionSamples.GetBuffer())[0];
  double y = (_modelRateSamples.GetBuffer())[0];

  double x2 = x*x;
  double px2 = _prevDistortion*_prevDistortion;
  _Sx = UpdateRunningSum(_prevDistortion, x, _Sx);
  _Sy = UpdateRunningSum(_prevModelRate, y, _Sy);
  _Sxy = UpdateRunningSum(_prevDistortion*_prevModelRate, x*y, _Sxy);
  _Sx2 = UpdateRunningSum(px2, x2, _Sx2);

  _Spr = UpdateRunningSum(_prevModelPredRate, (_modelPredRateSamples.GetBuffer())[0], _Spr);
  _Smr = UpdateRunningSum(_prevModelMismatchRate, (_modelMismatchRateSamples.GetBuffer())[0], _Smr);

  _modelFit = _Smr / _Spr;

  /// Determine new R-D model parameters.
  double tempValForSlopeBoundaryCheck = -1.0 / (log((_meanDiffSamples.GetBuffer())[0] / _distUpper));
  /// Improvements on the current parameters applied to the objective function. Find the Cramer's Rule 
  /// solution and test it against boundary conditions. If the solution is out of bounds then use a gradient
  /// decsent algorithm to modify the current parameters. Choose only those solutions that improve on the
  /// objective function.
  int si;
  /// Cramer's Solution and objective function (aa,bb) with current objective function (_a,_b)
  double aa = 0.0;
  double bb = 0.0;
  CramersRuleSoln(_Sx2, _Sx, _Sx, (double)_numOfFrames, _Sxy, _Sy, &aa, &bb);
  double currObjFunc = 0.0;
  double cramerObjFunc = 0.0;
  for (si = 0; si < _numOfFrames; si++)
  {
    double crs = (_modelRateSamples.GetBuffer())[si];
    double ds = (_distortionSamples.GetBuffer())[si];
    double curr = crs - (_a*ds) - _b;
    currObjFunc += curr*curr;
    double cramer = crs - (aa*ds) - bb;
    cramerObjFunc += cramer*cramer;
  }//end for si...
   /// Outside boundary conditions.
  bool cramerDisqualified = (bb <= 0.0) || (aa <= (bb*tempValForSlopeBoundaryCheck));

  /// Choose best improved solution.
  if (!cramerDisqualified && (cramerObjFunc <= currObjFunc))
  {
    _a = aa;
    _b = bb;
  }//end if !cramerDisqualified...
  else ///< use gradient descent change if Cramer's soln is out of bounds.
  {
    /// Determine the gradient vector at current parameters (_a,_b).
    double dsda = 2.0*((_a*_Sx2) + (_b*_Sx) - _Sxy);
    double dsdb = 2.0*((_a*_Sx) + (_b*(double)_numOfFrames) - _Sy);
    /// Search for gamma.
    double gamma = 1.0;
    double a, b;
    double gradObjFunc = currObjFunc + 1.0; ///< Ensure while loop starts.
    int cnt = 0;
    bool goingDown = true;
    while ((cnt < 26) && (goingDown))
    {
      b = _b - (gamma * dsdb);
      a = _a - (gamma * dsda);
      double lclGradObjFunc = 0.0;
      for (si = 0; si < _numOfFrames; si++)
      {
        double grad = (_modelRateSamples.GetBuffer())[si] - (a*(_distortionSamples.GetBuffer())[si]) - b;
        lclGradObjFunc += grad*grad;
      }//end for si...

       /// If not descending then back up to previous a & b and get out.
      if (cnt && (lclGradObjFunc >= gradObjFunc))
      {
        goingDown = false;
        gamma = gamma*2.0;  ///< Reverse back.
        b = _b - (gamma * dsdb);
        a = _a - (gamma * dsda);
      }//end if lclGradObjFunc...
      else
      {
        gradObjFunc = lclGradObjFunc;
        gamma = gamma / 2.0;
      }//end else...

      cnt++;
    }//end while cnt...

    if ((gradObjFunc <= currObjFunc) && (a > (b*tempValForSlopeBoundaryCheck)) && (b > 0.0))
    {
      _a = a;
      _b = b;
    }//end if gradObjFunc...
  }//end else...

   /// Update mean diff running sums.
  _SEy = UpdateRunningSum(_prevMeanDiff, (_meanDiffSamples.GetBuffer())[0], _SEy);
  _SEiy = 0.0;
  for (int i = 0; i < _numOfFrames; i++)
    _SEiy += (_numOfFrames - i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.

  /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SEiy, _SEy, &_a1, &_a2);

  /// Update short term mean differnce members.
  _SEy_s = 0.0;
  _SEiy_s = 0.0;
  for (int i = 0; i < RCIL_NUM_SHORT_TERM_SAMPLES; i++)
  {
    _SEiy_s += (RCIL_NUM_SHORT_TERM_SAMPLES - i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
    _SEy_s += (_meanDiffSamples.GetBuffer())[i];
  }//end for i...
   /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2_s, _SEi_s, _SEi_s, (double)RCIL_NUM_SHORT_TERM_SAMPLES, _SEiy_s, _SEy_s, &_a1_s, &_a2_s);

  /// Determine R sqr.
  _R2 = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), _numOfFrames, _a1, _a2);
  _R2_s = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), RCIL_NUM_SHORT_TERM_SAMPLES, _a1_s, _a2_s);

  /// Update total buffer rate running sums.
  _Sbuff = UpdateRunningSum(_prevBuffRate, (_buffRateSamples.GetBuffer())[0], _Sbuff);

}//end ModelUpdate.
========== END FILE: CodecUtils/RateControlImplLog.cpp ==========

========== BEGIN FILE: CodecUtils/RateControlImplLog.h ==========
Bundle entry: 108
Original bytes: 10494
Original SHA-256: aa6115a6c9a7c8bc9f45f5f9fa23016861b2c77a5677e2b620f2d5b8399b63c3
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE			  : RateControlImplLog

TAG				    : RCIL

FILE NAME		  : RateControlImplLog.h

DESCRIPTION		: A class to hold a natural log function  model for the frame buffer rate rate control to
				        match an average rate stream.

COPYRIGHT		  : (c)CSIR 2007-2017 all rights resevered

LICENSE			  : Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
				        modification, are permitted provided that the following conditions 
				        are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RATECONTROLIMPLLOG_H
#define _RATECONTROLIMPLLOG_H

#pragma once

#include  <math.h>
#include  "IRateControl.h"
#include  "GeneralUtils/MeasurementTable.h"

//#define RCIL_DUMP_RATECNTL  1
#define RCIL_DUMP_FILENAME "C:/Users/KFerguson/Documents/Excel/VideoEvaluation/RateControlLog_"	///< File name head only

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RateControlImplLog : public IRateControl
{
public:
  RateControlImplLog(void) 
  { _a = 0.2; _b = 1.4; _numOfFrames = 0; 
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 67108864.0; _distLower = 256.0;
  }
  RateControlImplLog(double modelparam_a, double modelparam_b) 
  { _a = modelparam_a; _b = modelparam_b; _numOfFrames = 0; 
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 67108864.0; _distLower = 256.0;
  }
  virtual ~RateControlImplLog() { Destroy(); }

/// IRateControl Interface methods.
public:
  int	  Create(int numOfFrames);
  void	Destroy(void);
  int   GetFameBufferLength(void) { return(_numOfFrames); }
  void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) 
        { _rateUpper = rateUpper; _rateLower = rateLower; _distUpper = distUpper; _distLower = distLower; }

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target coeff rate.
  int PredictDistortion(double targetAvgRate, double rateLimit);
  /// Post-encoding: Add samples to the fifo buffers and hold the sample that is discarded.
  void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae);
  /// Return average rate across the buffer as the performance measure.
  double GetPerformanceMeasure(void)  { return(_modelFit); }

  /// Is the data in the fifos valid.
  int ValidData(void) 
    { if(!_distortionSamples.Empty() && !_meanDiffSamples.Empty() && !_modelRateSamples.Empty() && !_buffRateSamples.Empty()) return(1); return(0); }
  /// Was the prediction calculation out of bounds?
  bool OutOfBounds(void) { return(_outOfBoundsFlag); }
  /// Who is the culprit?
  bool UpperDistortionOverflow(void)  { return(_upperDistortionOverflowFlag); }
  bool LowerDistortionOverflow(void)  { return(_lowerDistortionOverflowFlag); }
  bool UpperRateOverflow(void)        { return(_upperRateOverflowFlag); }
  bool LowerRateOverflow(void)        { return(_lowerRateOverflowFlag); }
  /// Reset the fifos to empty.
  void Reset(void)
  { _modelMismatchRateSamples.MarkAsEmpty(); _modelPredRateSamples.MarkAsEmpty(); _distortionSamples.MarkAsEmpty(); 
    _modelRateSamples.MarkAsEmpty(); _buffRateSamples.MarkAsEmpty(); _meanDiffSamples.MarkAsEmpty();  }
  /// In this implementation only the mean abs err is used to indicate the degree of scene change. It is immediately reset to zero after use.
  void SignalSceneChange(double mse, double mae) { _mseSignal = mae; }

  /// Utility functions.
  void Dump(const char* filename);  ///< Requires RCIL_DUMP_RATECNTL to be set.
  void Dump(void);                  ///< Requires RCIL_DUMP_FILENAME to be defined.

/// Further implementation specific public methods.
public:

/// Private methods.
protected:
  /// These following group of methods must be called in this exact order because they operate
  /// on members that are interdependant.
  void PutMeanDiff(double meandiff, bool initialise) 
    { if(meandiff < 1.0) meandiff = 1.0;
      PutLinearMeasure(_meanDiffSamples, meandiff, &_prevMeanDiff, initialise); }
  void PutDistortion(double distortion, bool initialise) ///< Must only be called after a call to PutMeanDiff(). 
    { if(distortion < 1.0) distortion = 1.0;
      PutLogMeasure(_distortionSamples, ((_meanDiffSamples.GetBuffer())[0])/distortion, &_prevDistortion, initialise); }
  void PutModelRate(double rate, bool initialise) 
    { PutLinearMeasure(_modelRateSamples, rate, &_prevModelRate, initialise); }
  void PutBuffRate(double rate, bool initialise) 
    { PutLinearMeasure(_buffRateSamples, rate, &_prevBuffRate, initialise); }
  void PutPredRate(double rate, bool initialise) ///< Must only be called after PutDistortion().  
    { 
      double predRate = _a*(_distortionSamples.GetBuffer())[0] + _b;
      PutLinearMeasure(_modelPredRateSamples, predRate, &_prevModelPredRate, initialise);
      double mismatch = fabs(rate - predRate);
      PutLinearMeasure(_modelMismatchRateSamples, mismatch, &_prevModelMismatchRate, initialise);
    }

  double GetMostRecentModelRate(void) { return((_modelRateSamples.GetBuffer())[0]); }
  double GetMostRecentBuffRate(void) { return((_buffRateSamples.GetBuffer())[0]); }
  double GetMostRecentMeanDiff(void) { return((_meanDiffSamples.GetBuffer())[0]); }

  /// Model equations.
  double  ModelDistortion(double rate, double a, double b, double var) { return(var*exp((b - rate)/a)); }
  double  ModelRate(double distortion, double a, double b, double var) { return((a*log(var/distortion)) + b);}
  double  ModelMeanDifference(void);
  void    ModelInitialise(void);
  void    ModelUpdate(void);

  /// Model fit R^2 support.
  double RSqrLinRevOrder(double* samples, int length, double mlin, double clin);

/// Constant members.
public:

/// Common members.
protected:
	int		_numOfFrames;

  /// Clip the values of the rate and distortion to these limits.
  double    _rateUpper;
  double    _rateLower;
  double    _distUpper;
  double    _distLower;

  Fifo      _meanDiffSamples;     ///< Mean differnce between samples of frames.
  double    _prevMeanDiff;
  Fifo      _buffRateSamples;     ///< Stream rate including headers of frames.
  double    _prevBuffRate;
  Fifo      _modelRateSamples;    ///< Model rate is the stream rate.
  double    _prevModelRate;
  Fifo      _distortionSamples;   ///< Dmax for the frames.
  double    _prevDistortion;
  /// Signal when the predicted values are not valid due to out of range errors. Use
  /// this signal to prevent contributions to the model data.
  bool      _outOfBoundsFlag;
  bool      _upperDistortionOverflowFlag;
  bool      _lowerDistortionOverflowFlag;
  bool      _upperRateOverflowFlag;
  bool      _lowerRateOverflowFlag;

  /// To update the constants, _a and _b, Cramer's Rule is used to solve the linear equation 
  /// for a least mean squares criterion curve fit. Running sums are used.
  double    _Sxy;
  double    _Sx2;
  double    _Sx;
  double    _Sy;
  double    _a; ///< Log model constants.
  double    _b;

  /// The prediction of Mean Diff requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants a1 and a2. A long term and a
  /// a short term model are used.
  double    _SEi;   ///< Intermediate persistant values for Cramer's Rule calculation.
  double    _SEi2;
  double    _SEy;
  double    _SEiy;
  double    _a1;    ///< Linear model constants.
  double    _a2;
  double    _R2;    ///< Statistical R^2 value to compare performance of long term vs short term fit.
  /// Short term samples. No. of samples is fixed to the most recent in the mean diff sample fifo.
  double    _SEi_s;
  double    _SEi2_s;
  double    _SEy_s;
  double    _SEiy_s;
  double    _a1_s;
  double    _a2_s;
  double    _R2_s;

  /// Buffer rate control for average bit rate.
  double    _Sbuff;

  /// Measure the performance by the model accuracy.
  double    _modelFit;
  Fifo      _modelPredRateSamples;      ///< Model predicted rate is that defined by _a and _b.
  double    _prevModelPredRate;
  Fifo      _modelMismatchRateSamples;  ///< Abs diff between actual rate and model predicted rate.
  double    _prevModelMismatchRate;
  double    _Spr;                       ///< Fifo sum of pred model rate;
  double    _Smr;                       ///< Fifo sum of mismatch rate;

  /// Signalling parameters.
  double    _mseSignal;

  MeasurementTable  _RCTable;
  int               _RCTableLen;
  int               _RCTablePos;
#ifdef RCIL_DUMP_RATECNTL
  double            _predMD;
  double            _MD;
  double            _predDmax;
  double            _predRate;
  double            _rate;
#endif
};// end class RateControlImplLog.

#endif	// _RATECONTROLIMPLLOG_H
========== END FILE: CodecUtils/RateControlImplLog.h ==========

========== BEGIN FILE: CodecUtils/RateControlImplMultiModel.cpp ==========
Bundle entry: 109
Original bytes: 11194
Original SHA-256: 2fa6c8ed25128bc2bae1e7902000b571ccf1e47ded91772ab0df34a9f77e01e5
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImplMultiModel

TAG						: RCIMM

FILE NAME			: RateControlImplMultiModel.cpp

DESCRIPTION		: A class to hold a power function  model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#endif

/// The rate control models used by this model.
#include "RateControlImplQuad.h"
#include "RateControlImplPow.h"
#include "RateControlImplLog.h"

#include "RateControlImplMultiModel.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
RateControlImplMultiModel::RateControlImplMultiModel(double modelparms[][2], int nummodels) 
{ 
  ResetMembers(); 
  for(int i = 0; i < nummodels; i++)
  {
    _modelParam[i][0] = modelparms[i][0];
    _modelParam[i][1] = modelparms[i][1];
  }//end for i...
} // end constructor.

void RateControlImplMultiModel::ResetMembers(void)
{
  _numOfFrames  = 0;
  _rateUpper    = 24.0; 
  _rateLower    = 0.0001; 
  _distUpper    = 16777216.0; 
  _distLower    = 1024.0;

  _prevPredModelUsed   = QUAD;
  _modelParam[QUAD][0] = 40.0;
  _modelParam[QUAD][1] = 20000.0;
  _modelParam[POW][0]  = 15000.0;
  _modelParam[POW][1]  = -1.3;
  _modelParam[LOG][0]  = 0.2;
  _modelParam[LOG][1]  = 1.4;
  for(int i = 0; i < MODELS; i++)
    _model[i] = NULL;

//////////////////////////////////
  _modelCount[0] = 0;
  _modelCount[1] = 0;
  _modelCount[2] = 0;
}//end ResetMembers.

int RateControlImplMultiModel::Create(int numOfFrames)
{
  /// Clean up first.
  Destroy();

  _numOfFrames = numOfFrames;

  _outOfBoundsFlag    = false;

  /// Implementation specific construction for each model.
  _model[QUAD] = new RateControlImplQuad(_modelParam[QUAD][0], _modelParam[QUAD][1]);
  _model[POW]  = new RateControlImplPow(_modelParam[POW][0], _modelParam[POW][1]);
  _model[LOG]  = new RateControlImplLog(_modelParam[LOG][0], _modelParam[LOG][1]);
  if(!ModelsActive()) 
    return(0); ///< Mem alloc of classes failed.

  /// Create the internal model controllers.
  for(int m = 0; m < MODELS; m++)
    if(!_model[m]->Create(numOfFrames))
      return(0);

  _prevPredModelUsed = QUAD;

  _RCTableLen = 0;
  _RCTablePos = 0;

#ifdef RCIMM_DUMP_RATECNTL
  _RCTableLen = 500;
	_RCTable.Create(8, _RCTableLen);

  _RCTable.SetHeading(0, "Frame");
  _RCTable.SetDataType(0, MeasurementTable::INT);
  _RCTable.SetHeading(1, "Dmax");
  _RCTable.SetDataType(1, MeasurementTable::INT);
  _RCTable.SetHeading(2, "Rate");
  _RCTable.SetDataType(2, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(3, "Pred Rate");
  _RCTable.SetDataType(3, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(4, "Pred Mean Diff");
  _RCTable.SetDataType(4, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(5, "Mean Diff");
  _RCTable.SetDataType(5, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(6, "RD a");
  _RCTable.SetDataType(6, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(7, "RD b");
  _RCTable.SetDataType(7, MeasurementTable::DOUBLE);

  _predMD           = 0.0;
  _MD               = 0.0;
  _predDmax         = 0.0;
  _predRate         = 0.0;
  _rate             = 0.0;
#endif

  return(1);
}//end Create.

void RateControlImplMultiModel::Destroy(void)
{
  _RCTable.Destroy();

  for(int m = 0; m < MODELS; m++)
  {
    if(_model[m] != NULL)
    {
      _model[m]->Destroy();
      delete _model[m];
    }//end if _model...
    _model[m] = NULL;
  }//end for m...

  _numOfFrames = 0;
  _prevPredModelUsed = QUAD;

///////////////////////////////////
  int q = _modelCount[0];
  int p = _modelCount[1];
  int l = _modelCount[2];

}//end Destroy.

void RateControlImplMultiModel::SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) 
{ 
  _rateUpper = rateUpper; 
  _rateLower = rateLower; 
  _distUpper = distUpper; 
  _distLower = distLower; 

  if(ModelsActive())
  {
    _model[QUAD]->SetRDLimits(rateUpper, rateLower, distUpper/4, sqrt(distLower)); ///< Quad uses abs distortion measurements.
    _model[POW]->SetRDLimits(rateUpper, rateLower, distUpper, distLower);
    _model[LOG]->SetRDLimits(rateUpper, rateLower, distUpper, distLower);
  }//end if (_model[QUAD] != NULL)...
}//end SetRDLimits.

void RateControlImplMultiModel::Reset(void)
{
  for(int m = 0; m < MODELS; m++)
    _model[m]->Reset();

  _prevPredModelUsed = QUAD;
}//end Reset.

void RateControlImplMultiModel::Dump(const char* filename)
{
  if(_RCTablePos > 0)
    _RCTable.Save(filename, ",", 1);
  _RCTablePos = 0;
}//end Dump.

/*
---------------------------------------------------------------------------
	Public Interface Methods.
---------------------------------------------------------------------------
*/

///---------------------- Post-Encoding Measurements --------------------------

/// Add samples to the fifo buffers and hold the sample that is discarded. The
/// last discarded value is needed in the running sum update process.

/** Store model measurements after encoding a frame.
All rate measurements are in bpp. This implementation does not use the mae parameter.
@param rate       : Total rate of the frame including headers.
@param coeffrate  : Not used in this implementation.
@param distortion : Implementation specific distortion of the frame.
@param mse        : Implementation specific signal mean square difference between pels in the frame.
@param mae        : Implementation specific signal mean absolute difference between pels in the frame.
@return           : none.
*/
void RateControlImplMultiModel::StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae)
{ 
  /// Pass on the measurements to the all the models for initialisation.
  for(int m = 0; m < MODELS; m++)
    _model[m]->StoreMeasurements(rate, coeffrate, distortion, mse, mae);

#ifdef RCIMM_DUMP_RATECNTL
  _MD   = GetMostRecentMeanDiff();
  _rate = GetMostRecentBuffRate();

  /// This method is the last to be called after processing a frame. Therefore dump here.
  if(_RCTablePos < _RCTableLen)
  {
    _RCTable.WriteItem(0, _RCTablePos, _RCTablePos);            ///< Frame
    _RCTable.WriteItem(1, _RCTablePos, (int)(0.5 + _predDmax)); ///< Dmax
    _RCTable.WriteItem(2, _RCTablePos, _rate);                  ///< Rate
    _RCTable.WriteItem(3, _RCTablePos, _predRate);              ///< Pred Rate
    _RCTable.WriteItem(4, _RCTablePos, _predMD);                ///< Pred Mean Diff
    _RCTable.WriteItem(5, _RCTablePos, _MD);                    ///< Mean Diff
    _RCTable.WriteItem(6, _RCTablePos, _a);                     ///< Model parameter a
    _RCTable.WriteItem(7, _RCTablePos, _b);                     ///< Model parameter b

    _RCTablePos++;
  }//end if _RCTablePos... 
#endif

}//end StoreMeasurements.

///---------------------- Pre-Encoding Predictions --------------------------

/** Predict the distortion for the next frame from the desired average rate.
The distortion measure is predicted from the coeff rate (total rate - header rate) using
an appropriate R-D model. The header rate and the signal mean diff are predicted from the
previous measured frame data using linear extrapolation.
@param  targetAvgRate : Total targeted average rate (including headers).
@param  rateLimit     : Upper limit to predicted rate.
@return               : Predicted distortion.
*/
int RateControlImplMultiModel::PredictDistortion(double targetAvgRate, double rateLimit)
{
  ///------------------ Model Selection --------------------------------------------

  int DPpred  = _model[POW]->PredictDistortion(targetAvgRate, rateLimit);
  int DLpred  = _model[LOG]->PredictDistortion(targetAvgRate, rateLimit);


  /// The distortion will be predicted from the past best performing model. Default 
  /// best model is the first one in the list.
  int bestModel = 1;  ///< Skip QUAD for now.
  double bestPerf = _model[bestModel]->GetPerformanceMeasure();
  for(int m = bestModel+1; m < MODELS; m++) ///< Test against remaining models.
  {
    double perf = _model[m]->GetPerformanceMeasure();
    if(perf < bestPerf)
    {
      bestPerf = perf;
      bestModel = m;
    }//end if diff...
  }//end for m...

  double perfQuad = _model[QUAD]->GetPerformanceMeasure();
  double perfPow  = _model[POW]->GetPerformanceMeasure();
  double perfLog  = _model[LOG]->GetPerformanceMeasure();

  ///--------------- Distortion Prediction ------------------------------------------
  _prevPredModelUsed  = bestModel;
  int bestDistortion  = _model[bestModel]->PredictDistortion(targetAvgRate, rateLimit);
  _outOfBoundsFlag    = _model[bestModel]->OutOfBounds(); ///< Out of bounds is set in the PredictDistortion() method.

///////////////////////////////////
  _modelCount[bestModel]++;

#ifdef RCIMM_DUMP_RATECNTL
  _predRate = targetRate;
  _predMD   = predMD;
  _predDmax = bestDistortion;
#endif

  return(bestDistortion);
}//end PredictDistortion.

========== END FILE: CodecUtils/RateControlImplMultiModel.cpp ==========

========== BEGIN FILE: CodecUtils/RateControlImplMultiModel.h ==========
Bundle entry: 110
Original bytes: 5821
Original SHA-256: 9252a00452666779601ce74233c21d553b97817b594ffe5ffdd871695929966f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImplMultiModel

TAG						: RCIMM

FILE NAME			: RateControlImplMultiModel.h

DESCRIPTION		: A class to hold a multi-function model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RATECONTROLIMPLMULTIMODEL_H
#define _RATECONTROLIMPLMULTIMODEL_H

#pragma once

#include  <math.h>
#include  "Fifo.h"
#include  "IRateControl.h"

#include  "MeasurementTable.h"
//#define RCIMM_DUMP_RATECNTL  1

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RateControlImplMultiModel : public IRateControl
{
public:
  RateControlImplMultiModel(void) { ResetMembers(); }
  RateControlImplMultiModel(double modelparms[][2], int nummodels);
  virtual ~RateControlImplMultiModel() { Destroy(); }

/// IRateControl Interface methods.
public:
  int		Create(int numOfFrames);
  void	Destroy(void);
  int   GetFameBufferLength(void) { return(_numOfFrames); }
  void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower);

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target coeff rate.
  int PredictDistortion(double targetAvgRate, double rateLimit);
  /// Post-encoding: Add samples to the fifo buffers and hold the sample that is discarded.
  void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae);

  /// Return average rate across the buffer as the performance measure.
  double GetPerformanceMeasure(void) { return(0.0); }

  /// Data is valid if models are active.
  int ValidData(void) 
  { if(ModelsActive()) 
      if( (_model[QUAD]->ValidData())&&(_model[POW]->ValidData())&&(_model[LOG]->ValidData()) )
        return(1);
    return(0); 
  }
  /// Was the prediction calculation out of bounds?
  bool OutOfBounds(void) { return(_outOfBoundsFlag); }
  /// Reset the fifos. Use after a change in frame type.
  void Reset(void);

  /// Utility functions.
  void Dump(const char* filename);  ///< Requires RCIP_DUMP_RATECNTL to be set.

/// Further implementation specific public methods.
public:

/// Private methods.
protected:
  void ResetMembers(void);

  /// Check if the models exist.
  bool ModelsActive(void) { return( (_model[QUAD] != NULL)&&(_model[POW] != NULL)&&(_model[LOG] != NULL) ); }

  /// Model equations.
  double ModelDistortion(double rate, double a, double b, double var) { return(0.0); }
  double ModelRate(double distortion, double a, double b, double var) { return(0.0); }

/// Constant members.
public:
  /// Model list array referencing.
  static const int QUAD   = 0;
  static const int POW    = 1;
  static const int LOG    = 2;
  static const int MODELS = 3;  ///< Num of models

/// Common members.
protected:
	int				_numOfFrames;
  /// Clip the values of the rate and distortion to these limits.
  double    _rateUpper;
  double    _rateLower;
  double    _distUpper;
  double    _distLower;

  /// Model list.
  IRateControl* _model[3];          ///< Pointers to the three models {QUAD, POW, LOG}.
  double        _modelParam[3][2];  ///< Store initial model parameters _a and _b for each model.
  int           _prevPredModelUsed; ///< Remember the model that was used for the last prediction.

  /// Signal when the predicted values are not valid due to out of range errors. Use
  /// this signal to prevent contributions to the model data.
  bool      _outOfBoundsFlag;

//////////////////////////////////////
  int _modelCount[3];

  MeasurementTable  _RCTable;
  int               _RCTableLen;
  int               _RCTablePos;
#ifdef RCIMM_DUMP_RATECNTL
  double            _predDmax;
  double            _predRate;
  double            _rate;
#endif
};// end class RateControlImplMultiModel.

#endif	// _RATECONTROLIMPLMULTIMODEL_H
========== END FILE: CodecUtils/RateControlImplMultiModel.h ==========

========== BEGIN FILE: CodecUtils/RateControlImplPow.cpp ==========
Bundle entry: 111
Original bytes: 25048
Original SHA-256: 5aa2e4aea9093b1030a17b9913f1e7b2e5170699f94585ceed4f25fad16ee498
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImplPow

TAG						: RCIP

FILE NAME			: RateControlImplPow.cpp

DESCRIPTION		: A class to hold a power function  model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2016 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#endif

#include <sstream>
#include <stdlib.h>
#include <string.h>
#include "RateControlImplPow.h"

/*
---------------------------------------------------------------------------
Constants
---------------------------------------------------------------------------
*/
#define RCIP_NUM_SHORT_TERM_SAMPLES 4

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
int RateControlImplPow::Create(int numOfFrames)
{
  /// Clean up first.
  Destroy();

  if( (!_meanDiffSamples.Create(numOfFrames))       || (!_modelRateSamples.Create(numOfFrames))  || 
      (!_buffRateSamples.Create(numOfFrames))       || (!_distortionSamples.Create(numOfFrames)) ||
      (!_modelPredRateSamples.Create(numOfFrames))  || (!_modelMismatchRateSamples.Create(numOfFrames)) ) 
    return(0);

  _numOfFrames = numOfFrames; 
  _meanDiffSamples.Clear(); 
  _modelRateSamples.Clear(); 
  _buffRateSamples.Clear(); 
  _distortionSamples.Clear();
  _modelPredRateSamples.Clear();
  _modelMismatchRateSamples.Clear();

  _prevMeanDiff           = 0.0;
  _prevModelRate          = 0.0;
  _prevBuffRate           = 0.0;
  _prevDistortion         = 0.0;
  _prevModelPredRate      = 0.0;
  _prevModelMismatchRate  = 0.0;

  _outOfBoundsFlag    = false;

  _modelFit = 0.0;
  _Spr      = 0.0;
  _Smr      = 0.0;

  _Sx   = 0.0;
  _Sy   = 0.0;
  _Sxy  = 0.0;
  _Sx2  = 0.0;

  /// Long term mean difference
  _SEi  = (double)(numOfFrames*(numOfFrames+1))/2.0;
  _SEi2 = (double)(numOfFrames*(numOfFrames+1)*((2*numOfFrames)+1))/6.0;
  _SEy  = 0.0;
  _SEiy = 0.0;
  _a1   = 1.0;
  _a2   = 0.0;
  _R2   = 1.0;
  /// Short term
  _SEi_s  = (double)(RCIP_NUM_SHORT_TERM_SAMPLES*(RCIP_NUM_SHORT_TERM_SAMPLES + 1)) / 2.0;
  _SEi2_s = (double)(RCIP_NUM_SHORT_TERM_SAMPLES*(RCIP_NUM_SHORT_TERM_SAMPLES + 1)*((2 * RCIP_NUM_SHORT_TERM_SAMPLES) + 1)) / 6.0;
  _SEy_s  = 0.0;
  _SEiy_s = 0.0;
  _a1_s   = 1.0;
  _a2_s   = 0.0;
  _R2_s   = 1.0;

  _Sbuff = 0.0;

  _mseSignal = 0.0;

  _RCTableLen = 0;
  _RCTablePos = 0;

#ifdef RCIP_DUMP_RATECNTL
  _RCTableLen = 500;
	_RCTable.Create(8, _RCTableLen);

  _RCTable.SetHeading(0, "Frame");
  _RCTable.SetDataType(0, MeasurementTable::INT);
  _RCTable.SetHeading(1, "Dmax");
  _RCTable.SetDataType(1, MeasurementTable::INT);
  _RCTable.SetHeading(2, "Rate");
  _RCTable.SetDataType(2, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(3, "Pred Rate");
  _RCTable.SetDataType(3, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(4, "Pred Mean Diff");
  _RCTable.SetDataType(4, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(5, "Mean Diff");
  _RCTable.SetDataType(5, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(6, "RD a");
  _RCTable.SetDataType(6, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(7, "RD b");
  _RCTable.SetDataType(7, MeasurementTable::DOUBLE);

  int i;
  char charBuffer[8];
  for(i = 0; i < 16; i++)
  {
    _RCTable.SetHeading(i+8, (const char*)_itoa(i, charBuffer, 10) );
    _RCTable.SetDataType(i+8, MeasurementTable::DOUBLE);
    _RCTable.SetHeading(i+24, (const char*)_itoa(i, charBuffer, 10) );
    _RCTable.SetDataType(i+24, MeasurementTable::DOUBLE);
  }//end for i...

  _predMD           = 0.0;
  _MD               = 0.0;
  _predDmax         = 0.0;
  _predRate         = 0.0;
  _rate             = 0.0;
#endif

  return(1);
}//end Create.

void RateControlImplPow::Destroy(void)
{
  _RCTable.Destroy();
  _RCTableLen = 0;
  _RCTablePos = 0;

  _modelMismatchRateSamples.Destroy(); 
  _modelPredRateSamples.Destroy(); 
  _distortionSamples.Destroy(); 
  _modelRateSamples.Destroy(); 
  _buffRateSamples.Destroy(); 
  _meanDiffSamples.Destroy();

  _numOfFrames = 0;

}//end Destroy.

void RateControlImplPow::Dump(const char* filename)
{
  if(_RCTablePos > 0)
    _RCTable.Save(filename, ",", 1);
  _RCTablePos = 0;
}//end Dump.

void RateControlImplPow::Dump(void)
{
  std::ostringstream filename;
  filename << RCIP_DUMP_FILENAME;  ///< Head.
  filename << ".csv";              ///< Tail
  Dump(filename.str().c_str());
}//end Dump.

/*
---------------------------------------------------------------------------
	Public Interface Methods.
---------------------------------------------------------------------------
*/

///---------------------- Post-Encoding Measurements --------------------------

/// Add samples to the fifo buffers and hold the sample that is discarded. The
/// last discarded value is needed in the running sum update process.

/** Store model measurements after encoding a frame.
All rate measurements are in bpp. This implementation does not use the mae parameter.
@param rate       : Total rate of the frame including headers.
@param coeffrate  : Not used in this implementation.
@param distortion : Implementation specific distortion of the frame.
@param mse        : Implementation specific signal mean square difference between pels in the frame.
@param mae        : Implementation specific signal mean absolute difference between pels in the frame.
@return           : none.
*/
void RateControlImplPow::StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae)
{ 
  bool initialisationRequired = (bool)(!ValidData());  ///< Status prior to storing new measurement values.

#ifdef RCIP_DUMP_RATECNTL
  _MD   = mse;
  _rate = rate;

  /// This method is the last to be called after processing a frame. Therefore dump here prior to updating the params.
  if(_RCTablePos < _RCTableLen)
  {
    _RCTable.WriteItem(0, _RCTablePos, _RCTablePos);            ///< Frame
    _RCTable.WriteItem(1, _RCTablePos, (int)(0.5 + _predDmax)); ///< Dmax
    _RCTable.WriteItem(2, _RCTablePos, _predRate);              ///< Required Rate
    _RCTable.WriteItem(3, _RCTablePos, rate);                   ///< Actual Rate
    _RCTable.WriteItem(4, _RCTablePos, _predMD);                ///< Pred MSE
    _RCTable.WriteItem(5, _RCTablePos, mse);                    ///< Actual MSE
    _RCTable.WriteItem(6, _RCTablePos, _a);                     ///< Model parameter a
    _RCTable.WriteItem(7, _RCTablePos, _b);                     ///< Model parameter b

    /// These data points were used to find _a and _b used in the prediction.
    for(int ti = 0; ti < 16; ti++)
    {
      _RCTable.WriteItem(ti+8, _RCTablePos, (_distortionSamples.GetBuffer())[ti]);  ///< Model ln(mse/dmax) data points
      _RCTable.WriteItem(ti+24, _RCTablePos, (_modelRateSamples.GetBuffer())[ti]);  ///< Model rate data points points
    }//end for i...

    _RCTablePos++;
  }//end if _RCTablePos... 
#endif

  /// Store all new measurements. 
  PutMeanDiff(mse, initialisationRequired);      ///<  NB: Mean diff MUST be stored first as the others use its value.
  PutDistortion(distortion, initialisationRequired);  ///< Internally uses meandiff
  PutModelRate(rate, initialisationRequired);         ///< ln(r) to use in the curve fitting process.
  PutBuffRate(rate, initialisationRequired);          ///< Actual rate produced in the encoding process.
  PutPredRate(rate, initialisationRequired);          ///< Both the predicted rate and the mismatch rate.

  if (!initialisationRequired) ///< Update the running sums associated with the model. 
    ModelUpdate();
  else  ///< Indicates that there was no valid data in the model before storing these first samples.
        /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
    ModelInitialise();

}//end StoreMeasurements.

///---------------------- Pre-Encoding Predictions --------------------------

/** Predict the distortion for the next frame from the desired average rate.
The distortion measure is predicted from the coeff rate (total rate - header rate) using
an appropriate R-D model. The header rate and the signal mean diff are predicted from the
previous measured frame data using linear extrapolation.
@param  targetAvgRate : Total targeted average rate (including headers).
@param  rateLimit     : Upper limit to predicted rate.
@return               : Predicted distortion.
*/
int RateControlImplPow::PredictDistortion(double targetAvgRate, double rateLimit)
{
  _outOfBoundsFlag              = false;
  _upperDistortionOverflowFlag  = false;
  _lowerDistortionOverflowFlag  = false;
  _upperRateOverflowFlag        = false;
  _lowerRateOverflowFlag        = false;

  /// Default settings for the non-valid data case.
  double targetRate      = targetAvgRate;
  double targetRateLimit = rateLimit;

  ///------------------ Rate Prediction --------------------------------------
  if(ValidData())
  {
    /// Buffer averaging model: What must the target rate for the
    /// next N frames be to make the average over the rate buffer equal
    /// to the average target rate specified in the parameter?

    /// N past frames and recover in k frames: target rate = target avg rate*(N+k)/k - total buff/k.
    int numRecoverFrames = _numOfFrames;  ///< Make recovery same as past num of frames until further notice.
    targetRate = ((targetAvgRate * (double)(_numOfFrames + numRecoverFrames))/(double)numRecoverFrames) - (_Sbuff/(double)numRecoverFrames);

  }//end if ValidData...

  /// Keep the target rate within the upper rate limit.
  if(targetRate > targetRateLimit)
    targetRate = targetRateLimit;

  /// No less than the coeff floor rate.
  if(targetRate < 0.00)
    targetRate = _rateLower;

  ///--------------- Distortion Prediction -----------------------------------------

  /// Predict Mean Diff with linear extrapolation model. Select between a long term or
  /// short term prediction based on the best statistical R^2 fit with the model. Override
  /// the prediction if a scene change was signalled externally.
  double predMD = ModelMeanDifference();

  /// Model function solved for distortion.
  double distd = ModelDistortion(targetRate, _a, _b, predMD);

  /// Limit a decrease change in distortion (implying limiting an increase in rate) to dd = prevd - 0.25*prevd.
  double prevd = (_meanDiffSamples.GetBuffer())[0]*(exp((_distortionSamples.GetBuffer())[0]));
  double limit = prevd - (0.25*prevd);
  if((distd < limit)&&(prevd < _distUpper))
  {
    distd = limit;
    targetRate = ModelRate(distd, _a, _b, predMD);
  }//end if distd...

  /// Cannot be greater than 16x16x(256^2). In response, converge
  /// towards the upper distortion limit by halving from the previous 
  /// frame distortion.
  if (distd > _distUpper)
  {
    distd = prevd + (abs(_distUpper - prevd)*0.5);
    _outOfBoundsFlag = true;
    _upperDistortionOverflowFlag = true;
  }//end if distd...
   /// Cannot be less than 16x16x(2^2). Converge to lower distortion limit.
  if (distd < _distLower)
  {
    distd = prevd - (abs(prevd - _distLower)*0.5);
    _outOfBoundsFlag = true;
    _lowerDistortionOverflowFlag = true;
  }//end if distd...

   /// Update the target rate with changes in Dmax boundaries.
  if(_outOfBoundsFlag)
    targetRate = ModelRate(distd, _a, _b, predMD);

#ifdef RCIP_DUMP_RATECNTL
  _predRate = targetRate;
  _predMD   = predMD;
  _predDmax = distd;
#endif

  return((int)(distd + 0.5));
}//end PredictDistortion.

 /*
 ----------------------------------------------------------------------------------------------------
 Private Methods
 ----------------------------------------------------------------------------------------------------
 */

 /** Calculate R^2 from a sample list.
 Determine the R^2 statistical model fit within an array of samples. Only
 calculate for the length specified from the list and do it in reverse order.
 @param  samples : Sample list of values
 @param  length  : Length from the value list to use.
 @param  mlin    : Linear model slope.
 @param  clin    : Linear model y-intercept.
 @return         : R^2.
 */
double RateControlImplPow::RSqrLinRevOrder(double* samples, int length, double mlin, double clin)
{
  double mean = 0.0;
  for (int i = 0; i < length; i++)
    mean += samples[i];
  mean = mean / length;

  double SStot = 0.0;
  double SSres = 0.0;
  for (int i = 0; i < length; i++)
  {
    double x = samples[i];
    SStot += (x - mean)*(x - mean);
    SSres += (x - (mlin*(length - i) + clin))*(x - (mlin*(length - i) + clin));
  }//end for i...

  double R2 = 1.0;
  if (SStot != 0.0)
    R2 = 1.0 - (SSres / SStot);

  return(R2);
}//end RSqrLinRevOrder.

 /** Predict the mean difference between pels in the frame.
 Predict the frame Mean Diff with linear extrapolation model. Select between a long term or
 short term prediction based on the best statistical R^2 fit with the model. Override the
 prediction if a scene change was signalled externally and reset the signal to zero.
 @return : Predicted mean difference.
 */
double RateControlImplPow::ModelMeanDifference(void)
{
  double predMD;
  if (_mseSignal == 0.0)
  {
    if (_R2_s > _R2)  ///< Short term is closer to 1.0 than the long term (better fit).
      predMD = (_a1_s*(double)(RCIP_NUM_SHORT_TERM_SAMPLES + 1)) + _a2_s; ///< Mean diff samples are in reverse order.
    else
      predMD = (_a1*(double)(_numOfFrames + 1)) + _a2;
    /// Can never be negative. Use last value if prediction is negative.
    if (predMD < 0.0)
      predMD = (_meanDiffSamples.GetBuffer())[0];
  }//end if _mseSignal...
  else
  {
    predMD = _mseSignal;
    _mseSignal = 0.0;  ///< Clear the signal.
  }//end else...

  return(predMD);
}//end ModelMeanDifference.

 /** Initialise all R-D model buffers and persistant member variables.
 Initialise the fifo buffers for the R-D model, Mean Diff and Model prediction members. The
 fifo buffers must have some valid data in them and the model parameters must be reset prior
 to calling this method. The values that are updated on every StoreMeasurement() call are
 initialised here.
 @return : None.
 */
void RateControlImplPow::ModelInitialise(void)
{
  /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
  _Sx   = 0;
  _Sy   = 0;
  _Sxy  = 0;        ///< Power R-D.
  _Sx2  = 0;

  _modelFit = 0.0;  ///< Performance measures.
  _Spr      = 0.0;
  _Smr      = 0.0;

  _SEy  = 0.0;      ///< Linear Mean Diff.
  _SEiy   = 0.0;
  _SEy_s  = 0.0;
  _SEiy_s = 0.0;

  _Sbuff = 0.0;     ///< Frame bit buffer.

  for (int i = 0; i < _numOfFrames; i++)
  {
    ///< Power R-D.
    double x = (_distortionSamples.GetBuffer())[i];
    double y = (_modelRateSamples.GetBuffer())[i];

    double x2 = x*x;
    _Sx += x;
    _Sy += y;
    _Sxy += x*y;
    _Sx2 += x2;

    _Spr += (_modelPredRateSamples.GetBuffer())[i];
    _Smr += (_modelMismatchRateSamples.GetBuffer())[i];

    ///< Linear Mean Diff
    x = (_meanDiffSamples.GetBuffer())[i];
    /// _SEi and _SEi2 are constants.
    _SEy += x;
    /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
    /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
    /// from the last frame. Extrapolation will predict x[N+1].
    _SEiy += (_numOfFrames - i)*x; ///< The sample time series are in reverse order in the fifo.

                                   /// Frame bit buffer rate. 
    _Sbuff += (_buffRateSamples.GetBuffer())[i];

  }//end for i...
   /// Long term R sqr.
  _R2 = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), _numOfFrames, _a1, _a2);

  for (int i = 0; i < RCIP_NUM_SHORT_TERM_SAMPLES; i++)
  {
    double x = (_meanDiffSamples.GetBuffer())[i];
    _SEy_s += x;
    _SEiy_s += (RCIP_NUM_SHORT_TERM_SAMPLES - i)*x;
  }//end for i...
   /// Short term R sqr.
  _R2_s = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), RCIP_NUM_SHORT_TERM_SAMPLES, _a1_s, _a2_s);

}//end ModelInitialise.

/** Update all R-D model parameters.
Update the model parameters for the R-D model (ln(Dmax/md), ln(r)), Mean Diff and the running
sums. The latest data must have been loaded into the fifo buffers prior to calling this
method. The values are updated on every StoreMeasurement() call.
@return : None.
*/
void RateControlImplPow::ModelUpdate(void)
{
  /// Update (ln(Dmax/md), ln(r)) running sums.
  double x = (_distortionSamples.GetBuffer())[0];
  double y = (_modelRateSamples.GetBuffer())[0];

  double x2 = x*x;
  double px2 = _prevDistortion*_prevDistortion;
  _Sx = UpdateRunningSum(_prevDistortion, x, _Sx);
  _Sy = UpdateRunningSum(_prevModelRate, y, _Sy);
  _Sxy = UpdateRunningSum(_prevDistortion*_prevModelRate, x*y, _Sxy);
  _Sx2 = UpdateRunningSum(px2, x2, _Sx2);

  _Spr = UpdateRunningSum(_prevModelPredRate, (_modelPredRateSamples.GetBuffer())[0], _Spr);
  _Smr = UpdateRunningSum(_prevModelMismatchRate, (_modelMismatchRateSamples.GetBuffer())[0], _Smr);

  _modelFit = _Smr / _Spr;

  /// Determine new R-D model parameters.
//  double tempValForSlopeBoundaryCheck = 1.0 / (log(_distUpper / (_meanDiffSamples.GetBuffer())[0]));
//  double tempValForRateCheck          = log(_rateLower);
  /// Improvements on the current parameters applied to the objective function. Find the Cramer's Rule 
  /// solution and test it against boundary conditions. If the solution is out of bounds then use a gradient
  /// decsent algorithm to modify the current parameters. Choose only those solutions that improve on the
  /// objective function.

  /// Cramer's Solution and objective function (aa,bb) with current objective function (_a,_b)
  double aa = 0.0;
  double bb = 0.0;
  CramersRuleSoln(_Sx2, _Sx, _Sx, (double)_numOfFrames, _Sxy, _Sy, &bb, &aa);
  double logaa = aa;
  aa = exp(aa);
  double loga = log(_a);
  double currObjFunc    = ObjectiveFunction(_numOfFrames, log(_a), _b);
  double cramerObjFunc  = ObjectiveFunction(_numOfFrames, logaa, bb);
   /// Outside boubndary conditions.
//  bool cramerDisqualified = (aa < 24.0) || (aa > 100000.0) || (bb < -3.0) || (bb > -0.3);
//  bool cramerDisqualified = (aa <= 0.0) || (bb >= 0.0);// || (bb > ((tempValForRateCheck - logaa)*tempValForSlopeBoundaryCheck));
//  bool cramerDisqualified = !WithinModelBounds(aa, bb);

  /// Choose best improved solution.
  bool cramerInBounds = WithinModelBounds(aa, bb);
  if (cramerInBounds && (cramerObjFunc <= currObjFunc) )
  {
    _a = aa;
    _b = bb;
  }//end if cramerInBounds...
  else ///< Either out of bounds or no improvement on current solution.
  {
    /// Try gradient descent for a better solution.
    /// Determine the gradient vector at current parameters (_a,_b).
    double a, b;
    double gradObjFunc = GradientDescent(&a, &b);
    bool   gradInBounds = WithinModelBounds(a, b);

    if (gradInBounds && (gradObjFunc <= currObjFunc) )
    {
      _a = a;
      _b = b;
    }// end if gradInBounds...

    /// All other conditions leave _a and _b unchanged.
  }//end else...

/*
  if (!cramerDisqualified && (cramerObjFunc <= currObjFunc))
  {
    _a = aa;
    _b = bb;
  }//end if !cramerDisqualified...
  else ///< use gradient descent change if Cramer's soln is out of bounds.
  {
    /// Determine the gradient vector at current parameters (_a,_b).
    double a, b;
    double gradObjFunc = GradientDescent(&a, &b);

    if ( (gradObjFunc <= currObjFunc) && (a > 0) && (b < 0) && (b <= ((tempValForRateCheck - log(a))*tempValForSlopeBoundaryCheck)) )
//    if (gradObjFunc <= currObjFunc)
      {
      _a = a;
      _b = b;
    }//end if gradObjFunc...
  }//end else...
*/
   /// Update mean diff running sums.
  _SEy = UpdateRunningSum(_prevMeanDiff, (_meanDiffSamples.GetBuffer())[0], _SEy);
  _SEiy = 0.0;
  for (int i = 0; i < _numOfFrames; i++)
    _SEiy += (_numOfFrames - i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
  /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SEiy, _SEy, &_a1, &_a2);

  /// Update short term mean differnce members.
  _SEy_s = 0.0;
  _SEiy_s = 0.0;
  for (int i = 0; i < RCIP_NUM_SHORT_TERM_SAMPLES; i++)
  {
    _SEiy_s += (RCIP_NUM_SHORT_TERM_SAMPLES - i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
    _SEy_s += (_meanDiffSamples.GetBuffer())[i];
  }//end for i...
   /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2_s, _SEi_s, _SEi_s, (double)RCIP_NUM_SHORT_TERM_SAMPLES, _SEiy_s, _SEy_s, &_a1_s, &_a2_s);

  /// Determine R sqr.
  _R2 = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), _numOfFrames, _a1, _a2);
  _R2_s = RSqrLinRevOrder(_meanDiffSamples.GetBuffer(), RCIP_NUM_SHORT_TERM_SAMPLES, _a1_s, _a2_s);

  /// Update total buffer rate running sums.
  _Sbuff = UpdateRunningSum(_prevBuffRate, (_buffRateSamples.GetBuffer())[0], _Sbuff);

}//end ModelUpdate.

/** Determine new model parameters through gradient descent..
The input model parameters are the current (_a,_b). Find another new set (a,b) using gadient 
descent for an improved objective function.
@param a : Return model parameter a
@param b : Return model parameter b
@return  : New objective function value.
*/
double RateControlImplPow::GradientDescent(double* a, double* b)
{
  double la, lb;

  /// Determine the gradient vector at current parameters (_a,_b).
  double dsdb = 2.0*((_b*_Sx2) + (log(_a)*_Sx) - _Sxy);
  double dsda = 2.0*((_b*_Sx) + (log(_a)*(double)_numOfFrames) - _Sy) / _a;

  /// Start with obj function value slightly larger than the current obj function value.
  double gradObjFunc = ObjectiveFunction(_numOfFrames, log(_a), _b) + 1.0;

  /// Continuously halve gamma to find the best new (la, lb) parameters.
  double  gamma      = 1.0;
  int     cnt        = 0;
  bool    goingDown  = true;
  while ((cnt < 26) && (goingDown))
  {
    lb = _b - (gamma * dsdb);
    la = _a - (gamma * dsda);
    double lclGradObjFunc = ObjectiveFunction(_numOfFrames, log(la), lb);

    /// If not descending then back up to previous a & b and get out.
    if (cnt && (lclGradObjFunc >= gradObjFunc))
    {
      goingDown = false;
      gamma = gamma*2.0;  ///< Reverse back.
      lb = _b - (gamma * dsdb);
      la = _a - (gamma * dsda);
    }//end if lclGradObjFunc...
    else
    {
      gradObjFunc = lclGradObjFunc;
      gamma = gamma / 2.0;
    }//end else...

    cnt++;
  }//end while cnt...

  *a = la;
  *b = lb;
  return(gradObjFunc);
}//end GradientDescent.
========== END FILE: CodecUtils/RateControlImplPow.cpp ==========

========== BEGIN FILE: CodecUtils/RateControlImplPow.h ==========
Bundle entry: 112
Original bytes: 11626
Original SHA-256: 109b16927f1ca4e29f4003da4f45eecf0ecff5178764a90a2cd0fcb22390ec03
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImplPow

TAG						: RCIP

FILE NAME			: RateControlImplPow.h

DESCRIPTION		: A class to hold a power function  model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2016 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RATECONTROLIMPLPOW_H
#define _RATECONTROLIMPLPOW_H

#pragma once

#include  <math.h>
#include  "GeneralUtils/Fifo.h"
#include  "IRateControl.h"
#include  "GeneralUtils/MeasurementTable.h"

//#define RCIP_DUMP_RATECNTL  1
#define RCIP_DUMP_FILENAME "c:/keithf/Excel/VideoEvaluation/RateControlPow_" ///< File name head only

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RateControlImplPow : public IRateControl
{
public:
  RateControlImplPow(void) 
  { _a = 15000.0; _b = -1.3; _numOfFrames = 0; 
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 67108864.0; _distLower = 256.0;
  }
  RateControlImplPow(double modelparam_a, double modelparam_b) 
  { _a = modelparam_a; _b = modelparam_b; _numOfFrames = 0; 
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 67108864.0; _distLower = 256.0;
  }
  virtual ~RateControlImplPow() { Destroy(); }

/// IRateControl Interface methods.
public:
  int		Create(int numOfFrames);
  void	Destroy(void);
  int   GetFameBufferLength(void) { return(_numOfFrames); }
  void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) 
        { _rateUpper = rateUpper; _rateLower = rateLower; _distUpper = distUpper; _distLower = distLower; }

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target coeff rate.
  int PredictDistortion(double targetAvgRate, double rateLimit);
  /// Post-encoding: Add samples to the fifo buffers and hold the sample that is discarded.
  void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae);
  /// Return model mismatch as the performance measure.
  double GetPerformanceMeasure(void) { return(_modelFit); }

  /// Is the data in the fifos valid.
  int ValidData(void) 
      { if(!_distortionSamples.Empty() && !_meanDiffSamples.Empty() && !_modelRateSamples.Empty() && !_buffRateSamples.Empty()) return(1); return(0); }
  /// Was the prediction calculation out of bounds?
  bool OutOfBounds(void) { return(_outOfBoundsFlag); }
  /// Who is the culprit?
  bool UpperDistortionOverflow(void)  { return(_upperDistortionOverflowFlag); }
  bool LowerDistortionOverflow(void)  { return(_lowerDistortionOverflowFlag); }
  bool UpperRateOverflow(void)        { return(_upperRateOverflowFlag); }
  bool LowerRateOverflow(void)        { return(_lowerRateOverflowFlag); }
  /// Reset the fifos. Use after a change in frame type.
  void Reset(void) { _modelMismatchRateSamples.MarkAsEmpty(); _modelPredRateSamples.MarkAsEmpty(); _distortionSamples.MarkAsEmpty();
                     _modelRateSamples.MarkAsEmpty(); _buffRateSamples.MarkAsEmpty(); _meanDiffSamples.MarkAsEmpty(); }

  /// In this implementation only the mean sqr err is used to indicate the degree of scene change. The signal is immediately reset to zero after use.
  void SignalSceneChange(double mse, double mae) { _mseSignal = mse; }

  /// Utility functions.
  void Dump(const char* filename);  ///< Requires RCIP_DUMP_RATECNTL to be set.
  void Dump(void);                  ///< Requires RCIP_DUMP_FILENAME to be defined.

/// Further implementation specific public methods.
public:

/// Private methods.
protected:
  /// These following group of methods must be called in this exact order because they operate
  /// on members that are interdependant.
  void PutMeanDiff(double meandiff, bool initialise) 
    { if(meandiff < 1.0) meandiff = 1.0;
      PutLinearMeasure(_meanDiffSamples, meandiff, &_prevMeanDiff, initialise); }
  void PutDistortion(double distortion, bool initialise) ///< Must only be called after a call to PutMeanDiff(). 
    { if(distortion < 1.0) distortion = 1.0;
      PutLogMeasure(_distortionSamples, (distortion/(_meanDiffSamples.GetBuffer())[0]), &_prevDistortion, initialise); }
  void PutModelRate(double rate, bool initialise) 
    { PutLogMeasure(_modelRateSamples, rate, &_prevModelRate, initialise); }
  void PutBuffRate(double rate, bool initialise) 
    { PutLinearMeasure(_buffRateSamples, rate, &_prevBuffRate, initialise); }
  void PutPredRate(double rate, bool initialise) ///< Must only be called after PutDistortion().  
    { 
      double predRate = _a*pow(exp((_distortionSamples.GetBuffer())[0]), _b);
      PutLinearMeasure(_modelPredRateSamples, predRate, &_prevModelPredRate, initialise);
      double mismatch = fabs(rate - predRate);
      PutLinearMeasure(_modelMismatchRateSamples, mismatch, &_prevModelMismatchRate, initialise);
    }

  void PutLogMeasure(Fifo& samples, double m, double* prev, bool initialise)
    { if(m <= 0.0) m = 0.0001; 
      if(!initialise) *prev = samples.GetFirstOut(); else *prev = log(m); 
      samples.AddFirstIn(log(m)); }

  void PutLinearMeasure(Fifo& samples, double m, double* prev, bool initialise) 
    { if(!initialise) *prev = samples.GetFirstOut(); else *prev = m; 
      samples.AddFirstIn(m); }

  double GetMostRecentModelRate(void) { return(exp((_modelRateSamples.GetBuffer())[0])); }
  double GetMostRecentBuffRate(void) { return((_buffRateSamples.GetBuffer())[0]); }
  double GetMostRecentMeanDiff(void) { return((_meanDiffSamples.GetBuffer())[0]); }

  /// Model equations.
  double ModelDistortion(double rate, double a, double b, double var) { return(var*exp((log(rate/a))/b)); }
  double ModelRate(double distortion, double a, double b, double var) { return(a*pow((distortion/var), b));}
  double ModelMeanDifference(void);
  void   ModelInitialise(void);
  void   ModelUpdate(void);
  double GradientDescent(double* a, double* b);
  bool   WithinModelBounds(double a, double b) { return((a > 1.0) && (b < 0.0)); }
  double SlopeLimit(void) { return(log(_rateLower / _rateUpper) / log(_distUpper / (_meanDiffSamples.GetBuffer())[0])); }
  double SlopeLimit(double a) { return(log(_rateLower / a) / log(_distUpper / (_meanDiffSamples.GetBuffer())[0])); }

  double ObjectiveFunction(int length, double a, double b)
  {
    /// Param a enters as the log(a) for pow model.
    double loga = a;
    double objFunc = 0.0;
    for (int i = 0; i < length; i++)
    {
      double obj = (_modelRateSamples.GetBuffer())[i] - (b*(_distortionSamples.GetBuffer())[i]) - loga;
      objFunc += obj*obj;
    }//end for i...
    return(objFunc);
  }//end ObjectiveFunction.

  /// Model fit R^2 support.
  double RSqrLinRevOrder(double* samples, int length, double mlin, double clin);

/// Constant members.
public:

/// Common members.
protected:
	int				_numOfFrames;
  /// Clip the values of the rate and distortion to these limits.
  double    _rateUpper;
  double    _rateLower;
  double    _distUpper;
  double    _distLower;

  Fifo      _meanDiffSamples;     ///< Mean differnce between samples within frames.
  double    _prevMeanDiff;
  Fifo      _buffRateSamples;     ///< Stream rate including headers of frames.
  double    _prevBuffRate;
  Fifo      _modelRateSamples;    ///< Model rate is the ln(stream rate).
  double    _prevModelRate;
  Fifo      _distortionSamples;   ///< Dmax for the frames.
  double    _prevDistortion;
  /// Signal when the predicted values are not valid due to out of range errors. Use
  /// this signal to prevent contributions to the model data.
  bool      _outOfBoundsFlag;
  bool      _upperDistortionOverflowFlag;
  bool      _lowerDistortionOverflowFlag;
  bool      _upperRateOverflowFlag;
  bool      _lowerRateOverflowFlag;

  /// To update the constants, _a and _b, Cramer's Rule is used to solve the linear equation 
  /// for a least mean squares criterion curve fit. Running sums are used.
  double    _Sxy;
  double    _Sx2;
  double    _Sx;
  double    _Sy;
  double    _a; ///< Power model constants.
  double    _b;

  /// The prediction of Mean Diff requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants a1 and a2.
  double    _SEi;
  double    _SEi2;
  double    _SEy;
  double    _SEiy;
  double    _a1;  ///< Linear model constants.
  double    _a2;
  double    _R2;    ///< Statistical R^2 value to compare performance of long term vs short term fit.
  /// Short term samples. No. of samples is fixed to the most recent in the mean diff sample fifo.
  double    _SEi_s;
  double    _SEi2_s;
  double    _SEy_s;
  double    _SEiy_s;
  double    _a1_s;
  double    _a2_s;
  double    _R2_s;

  /// Buffer rate control for average bit rate.
  double    _Sbuff;

  /// Measure the performance by the model accuracy.
  double    _modelFit;
  Fifo      _modelPredRateSamples;      ///< Model predicted rate is that defined by _a and _b.
  double    _prevModelPredRate;
  Fifo      _modelMismatchRateSamples;  ///< Abs diff between actual rate and model predicted rate.
  double    _prevModelMismatchRate;
  double    _Spr;                       ///< Fifo sum of pred model rate;
  double    _Smr;                       ///< Fifo sum of mismatch rate;

  /// Signalling parameters.
  double    _mseSignal;

  MeasurementTable  _RCTable;
  int               _RCTableLen;
  int               _RCTablePos;
#ifdef RCIP_DUMP_RATECNTL
  double            _predMD;
  double            _MD;
  double            _predDmax;
  double            _predRate;
  double            _rate;
#endif
};// end class RateControlImplPow.

#endif	// _RATECONTROLIMPLPOW_H
========== END FILE: CodecUtils/RateControlImplPow.h ==========

========== BEGIN FILE: CodecUtils/RateControlImplQuad.cpp ==========
Bundle entry: 113
Original bytes: 21311
Original SHA-256: 84e9c15e010d1e647a326e8e319cf325d38340def837f4c8ef3889291d5087a3
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE			: RateControlImplQuad

TAG				: RCIQ

FILE NAME		: RateControlImplQuad.cpp

DESCRIPTION		: A class to hold the model for the frame buffer rate rate control to
                match an average rate stream. This class models the RD curve with an
                inverse quadratic function.

COPYRIGHT		: (c)CSIR 2007-2015 all rights resevered

LICENSE			: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#endif

#include <sstream>
#include <stdlib.h>
#include <string.h>
#include "RateControlImplQuad.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
int RateControlImplQuad::Create(int numOfFrames)
{
  /// Clean up first.
  Destroy();

  if( (!_meanDiffSamples.Create(numOfFrames))		|| (!_totalRateSamples.Create(numOfFrames))  || 
      (!_coeffRateSamples.Create(numOfFrames))		|| (!_distortionSamples.Create(numOfFrames))    ||
      (!_headerRateSamples.Create(numOfFrames))		|| (!_modelRateDiffSamples.Create(numOfFrames)) || 
	  (!_modelPredRateSamples.Create(numOfFrames))	|| (!_modelMismatchRateSamples.Create(numOfFrames)) )
	  return(0);

  _numOfFrames = numOfFrames; 
  _meanDiffSamples.Clear(); 
  _totalRateSamples.Clear(); 
  _coeffRateSamples.Clear(); 
  _distortionSamples.Clear();
  _headerRateSamples.Clear();
  _modelRateDiffSamples.Clear();
  _modelPredRateSamples.Clear();
  _modelMismatchRateSamples.Clear();

  _prevMeanDiff       = 0.0;
  _prevTotalRate      = 0.0;
  _prevCoeffRate      = 0.0;
  _prevDistortion     = 0.0;
  _prevHeaderRate     = 0.0;
  _prevModelRateDiff  = 0.0;
  _prevModelPredRate = 0.0;
  _prevModelMismatchRate = 0.0;

  _prevCoeffRatePred  = 0.0;
  _outOfBoundsFlag    = false;

  _modelFit = 0.0;
  _Spr		= 0.0;
  _Smr		= 0.0;

  _Sx   = 0.0;
  _Sy   = 0.0;
  _Sxy  = 0.0;
  _Sx2  = 0.0;

  _SEi  = (double)(numOfFrames*(numOfFrames+1))/2.0;
  _SEi2 = (double)(numOfFrames*(numOfFrames+1)*((2*numOfFrames)+1))/6.0;
  _SEy  = 0.0;
  _SEiy = 0.0;
  _a1   = 1.0;
  _a2   = 0.0;

  _Sbuff = 0.0;

  _SPy  = 0.0;
  _SPiy = 0.0;
  _p1   = 1.0;
  _p2   = 0.0;

  _SMy  = 0.0;
  _SMiy = 0.0;
  _m1   = 1.0;
  _m2   = 0.0;

  _mseSignal = 0.0;

  _RCTableLen = 0;
  _RCTablePos = 0;

#ifdef RCIQ_DUMP_RATECNTL
  _RCTableLen = 300;
	_RCTable.Create(11, _RCTableLen);

  _RCTable.SetHeading(0, "Frame");
  _RCTable.SetDataType(0, MeasurementTable::INT);
  _RCTable.SetHeading(1, "Dmax");
  _RCTable.SetDataType(1, MeasurementTable::INT);
  _RCTable.SetHeading(2, "Rate");
  _RCTable.SetDataType(2, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(3, "Pred Coeff Rate");
  _RCTable.SetDataType(3, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(4, "Coeff Rate");
  _RCTable.SetDataType(4, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(5, "Pred Head Rate");
  _RCTable.SetDataType(5, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(6, "Head Rate");
  _RCTable.SetDataType(6, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(7, "Pred Mean Diff");
  _RCTable.SetDataType(7, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(8, "Mean Diff");
  _RCTable.SetDataType(8, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(9, "RD a");
  _RCTable.SetDataType(9, MeasurementTable::DOUBLE);
  _RCTable.SetHeading(10, "RD b");
  _RCTable.SetDataType(10, MeasurementTable::DOUBLE);

  _predMD           = 0.0;
  _MD               = 0.0;
  _predHeaderRate  = 0.0;
  _headerRate      = 0.0;
  _predDmax         = 0.0;
  _predCoeffRate    = 0.0;
  _coeffRate        = 0.0;
  _rate             = 0.0;
#endif

  return(1);
}//end Create.

void RateControlImplQuad::Destroy(void)
{
  _RCTable.Destroy();
  _RCTableLen = 0;
  _RCTablePos = 0;

  _modelMismatchRateSamples.Destroy();
  _modelPredRateSamples.Destroy();
  _modelRateDiffSamples.Destroy();
  _headerRateSamples.Destroy(); 
  _distortionSamples.Destroy(); 
  _coeffRateSamples.Destroy(); 
  _totalRateSamples.Destroy(); 
  _meanDiffSamples.Destroy();

  _numOfFrames = 0;

}//end Destroy.

void RateControlImplQuad::Reset(void)
{
  _modelMismatchRateSamples.MarkAsEmpty();
  _modelPredRateSamples.MarkAsEmpty();
  _modelRateDiffSamples.MarkAsEmpty();
  _headerRateSamples.MarkAsEmpty(); 
  _distortionSamples.MarkAsEmpty(); 
  _coeffRateSamples.MarkAsEmpty(); 
  _totalRateSamples.MarkAsEmpty(); 
  _meanDiffSamples.MarkAsEmpty();

}//end Reset.

void RateControlImplQuad::Dump(const char* filename)
{
  if(_RCTablePos > 0)
    _RCTable.Save(filename, ",", 1);
  _RCTablePos = 0;
}//end Dump.

void RateControlImplQuad::Dump(void)
{
	std::ostringstream filename;
	filename << RCIQ_DUMP_FILENAME;  ///< Head.
	filename << ".csv";              ///< Tail
	Dump(filename.str().c_str());
}//end Dump.

 /*
---------------------------------------------------------------------------
	Public Interface Methods.
---------------------------------------------------------------------------
*/

///---------------------- Post-Encoding Measurements --------------------------

/// Add samples to the fifo buffers and hold the sample that is discarded. The
/// last discarded value is needed in the running sum update process.

/** Store model measurements after encoding a frame.
All rate measurements are in bpp.
@param rate       : Total rate of the frame including headers.
@param coeffrate  : Rate of the frame coeff encoding without headers.
@param distortion : Implementation specific squared difference distortion of the frame.
@param mse        : Implementation specific signal mean square error of the frame.
@param mae        : Implementation specific signal mean absolute error of the frame.
@return           : none.
*/
void RateControlImplQuad::StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae)
{ 
  bool initialisationRequired = (bool)(!ValidData());  ///< Status prior to storing new measurement values.
  double meandiff = mae;

#ifdef RCIQ_DUMP_RATECNTL
  _MD			= mae;
  _coeffRate	= coeffrate;
  _rate			= rate;
  _headerRate	= rate - coeffrate;

  /// This method is the last to be called after processing a frame. Therefore dump here.
  if (_RCTablePos < _RCTableLen)
  {
	  _RCTable.WriteItem(0, _RCTablePos, _RCTablePos);  ///< P-Frame
	  _RCTable.WriteItem(1, _RCTablePos, (int)(0.5 + _predDmax)); ///< Dmax
	  _RCTable.WriteItem(2, _RCTablePos, _rate);  ///< Rate
	  _RCTable.WriteItem(3, _RCTablePos, _predCoeffRate);  ///< Pred Coeff Rate
	  _RCTable.WriteItem(4, _RCTablePos, _coeffRate);  ///< Coeff Rate
	  _RCTable.WriteItem(5, _RCTablePos, _predHeaderRate);  ///< Pred Head Rate
	  _RCTable.WriteItem(6, _RCTablePos, _headerRate);  ///< Head Rate
	  _RCTable.WriteItem(7, _RCTablePos, _predMD);  ///< Pred Mean Diff
	  _RCTable.WriteItem(8, _RCTablePos, _MD);  ///< Mean Diff
	  _RCTable.WriteItem(9, _RCTablePos, _a);  ///< Model parameter a
	  _RCTable.WriteItem(10, _RCTablePos, _b);  ///< Model parameter b

	  _RCTablePos++;
  }//end if _RCTablePos... 
#endif


   /// Store all new measurements.
  PutMeanDiff(meandiff, initialisationRequired);      ///<  NB: Mean diff MUST be stored first as the others use its value.
  PutDistortion(distortion, initialisationRequired);  ///< Internally uses meandiff
  PutCoeffRate(coeffrate, initialisationRequired);
  ///< Model mismatch is difference between predicted and actual coeff rates.
  PutModelRateDiff(_prevCoeffRatePred - GetMostRecentCoeffRate(), initialisationRequired);
  PutTotalRate(rate, initialisationRequired);
  PutHeaderRate(GetMostRecentTotalRate() - GetMostRecentCoeffRate(), initialisationRequired);

  if (!initialisationRequired) ///< Update the running sums associated with the model. 
    ModelUpdate();
  else  ///< Indicates that there was no valid data in the model before storing these first samples.
    /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
    ModelInitialise();

}//end StoreMeasurements.

///---------------------- Pre-Encoding Predictions --------------------------

/** Predict the distortion for the next frame from the desired average rate.
The distortion measure is predicted from the coeff rate (total rate - header rate) using
an appropriate R-D model. The header rate and the signal mean diff are predicted from the
previous measured frame data using linear extrapolation.
@param  targetAvgRate : Total targeted average rate (including headers).
@param  rateLimit     : Upper limit to predicted rate.
@return               : Predicted square error distortion.
*/
int RateControlImplQuad::PredictDistortion(double targetAvgRate, double rateLimit)
{
  _outOfBoundsFlag = false;
  _upperDistortionOverflowFlag = false;
  _lowerDistortionOverflowFlag = false;
  _upperRateOverflowFlag = false;
  _lowerRateOverflowFlag = false;

  /// Default settings for the non-valid data case.
  double targetCoeffRate      = targetAvgRate;
  double targetCoeffRateLimit = rateLimit;
  double predHeaderRate       = 0.02;

  ///------------------ Rate Prediction --------------------------------------
  if(ValidData())
  {
    /// Buffer averaging model: What must the target rate for the
    /// next N frames be to make the average over the rate buffer equal
    /// to the average target rate specified in the parameter?

    /// N past frames and recover in k frames: target rate = target avg rate*(N+k)/k - total buff/k.
    int numRecoverFrames = _numOfFrames;
    double targetRate = ((targetAvgRate * (double)(_numOfFrames + numRecoverFrames))/(double)numRecoverFrames) - (_Sbuff/(double)numRecoverFrames);

    /// Check that the result is reasonable. If not then force it to some arbitrary minimum.
    if(targetRate < 0.0)  
      targetRate = (_headerRateSamples.GetBuffer())[0] + _rateLower;

    /// Predict the header rate with linear extrapolation model.
    predHeaderRate = (_p1*(double)(_numOfFrames+1)) + _p2;
     /// Check that the result is reasonable. If not, use the last entry.
    if( (predHeaderRate > targetAvgRate) || (predHeaderRate < 0.0) ) 
      predHeaderRate = (_headerRateSamples.GetBuffer())[0];          

    /// Remove the header rate to predict the coeff rate.
    targetCoeffRate = targetRate - predHeaderRate;
    targetCoeffRateLimit = rateLimit - predHeaderRate;

  }//end if ValidData...
  else  ///< There is no valid data in the fifo buffers yet.
  {
    if(targetAvgRate > 0.02) ///< Guess header rate at 0.02 bpp.
      targetCoeffRate = targetAvgRate - 0.02;
  }//end else...

  /// Keep the target rate within the upper rate limit.
  if(targetCoeffRate > targetCoeffRateLimit)
    targetCoeffRate = targetCoeffRateLimit;

  /// No less than the coeff floor rate.
  if(targetCoeffRate < 0.00)
    targetCoeffRate = _rateLower;
  _prevCoeffRatePred = targetCoeffRate;

  ///--------------- Distortion Prediction -----------------------------------------

  /// Predict Mean Diff with linear extrapolation model. Override
  /// the prediction if a scene change was signalled externally.
  double predMD = ModelMeanDifference();

  /// Make prediction.
  double distd = 0.0;
  double core = (_a*_a) + (4.0*_b*targetCoeffRate);
  if(core >= 0.0)
    distd = ModelDistortion(targetCoeffRate, _a, _b, predMD);
  else
    distd = (predMD*_a)/targetCoeffRate;

  /// Check bounds on distortion.
  if(distd > _distUpper)
  {
    distd = _distUpper;
    _outOfBoundsFlag = true;
	_upperDistortionOverflowFlag = true;
  }//end if distd...
  /// Cannot be less than 16x16x(2^2)
  if(distd < _distLower)
  {
    distd = _distLower;
    _outOfBoundsFlag = true;
	_lowerDistortionOverflowFlag = true;
  }//end if distd...

  /// Update the target coeff rate with changes in Dmax boundaries.
  if(_outOfBoundsFlag)
  {
    targetCoeffRate = ModelRate(distd, _a, _b, predMD);
    _prevCoeffRatePred = targetCoeffRate;
  }//end if _outOfBoundsFlag...

#ifdef RCIQ_DUMP_RATECNTL
  _predHeaderRate   = predHeaderRate;
  _predCoeffRate    = targetCoeffRate;
  _predMD           = predMD;
  _predDmax         = distd;
#endif

  /// Convert absolute distortion to square distortion.
  //return((int)((distd*distd) + 0.5));
  return((int)(distd + 0.5));
}//end PredictDistortion.

 /*
 ---------------------------------------------------------------------------
 Public Interface Methods.
 ---------------------------------------------------------------------------
 */

/** Predict the mean difference between pels in the frame.
Predict the frame Mean Diff with linear extrapolation model. Override the prediction 
if a scene change was signalled externally and reset the signal to zero.
@return : Predicted mean difference.
*/
double RateControlImplQuad::ModelMeanDifference(void)
{
  double predMD;
  if (_mseSignal == 0.0)
  {
    /// Predict with linear extrapolation model.
    predMD = (_a1*(double)(_numOfFrames + 1)) + _a2;
    /// Can never be negative. Use last value if prediction is negative.
    if (predMD < 0.0)
      predMD = (_meanDiffSamples.GetBuffer())[0]; ///< Mean diff samples are in reverse order.
  }//end if _mseSignal...
  else
  {
    predMD = _mseSignal;
    _mseSignal = 0.0;  ///< Clear the signal.
  }//end else...

  return(predMD);
}//end ModelMeanDifference.

/** Initialise all R-D model buffers and persistant member variables.
Initialise the fifo buffers for the R-D model, Mean Diff and Model prediction members. The
fifo buffers must have some valid data in them and the model parameters must be reset prior
to calling this method. The values that are updated on every StoreMeasurement() call are
initialised here.
@return : None.
*/
void RateControlImplQuad::ModelInitialise(void)
{
  /// Initialise the fifo buffers for the R-D model, Mean Diff and Model Diff prediction models.
  _Sx = 0;
  _Sy = 0;
  _Sxy = 0;    ///< Quadratic R-D.
  _Sx2 = 0;

  _modelFit = 0.0;  ///< Performance measures.
  _Spr = 0.0;
  _Smr = 0.0;

  _SEy = 0.0;  ///< Linear Mean Diff
  _SEiy = 0.0;

  _SMy = 0.0;  ///< Linear Model Diff
  _SMiy = 0.0;

  _Sbuff = 0.0; ///< Frame bit buffer.

  _SPy = 0.0;  ///< Linear header rate
  _SPiy = 0.0;

  for (int i = 0; i < _numOfFrames; i++)
  {
    ///< Quadratic R-D.
    double x = (_distortionSamples.GetBuffer())[i];
    double y = (_coeffRateSamples.GetBuffer())[i];

    double x2 = x*x;
    _Sx += x;
    _Sy += y;
    _Sxy += y / x;
    _Sx2 += x2;

    _Spr += (_modelPredRateSamples.GetBuffer())[i];
    _Smr += (_modelMismatchRateSamples.GetBuffer())[i];

    ///< Linear Mean Diff
    x = (_meanDiffSamples.GetBuffer())[i];
    /// _SEi and _SEi2 are constants.
    _SEy += x;
    /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
    /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
    /// from the last frame. Extrapolation will predict x[N+1].
    _SEiy += (_numOfFrames - i)*x; ///< The sample time series are in reverse order in the fifo.

                                   ///< Linear Model Diff
    y = (_modelRateDiffSamples.GetBuffer())[i];
    /// _SEi and _SEi2 are constants.
    _SMy += y;
    _SMiy += (_numOfFrames - i)*y; ///< The sample time series are in reverse order in the fifo.

                                   /// Frame bit buffer.
    _Sbuff += (_totalRateSamples.GetBuffer())[i];

    /// Header rate.
    x = (_headerRateSamples.GetBuffer())[i];
    /// _SEi and _SEi2 are constants.
    _SPy += x;
    /// The sample time series are in reverse order in the fifo. x[fifo(0)] is x[_numOfFrames-1].
    /// The independent axis of the model describes samples at [1..N] where 1 is the oldest and N 
    /// from the last frame. Extrapolation will predict x[N+1].
    _SPiy += (_numOfFrames - i)*x; ///< The sample time series are in reverse order in the fifo.

  }//end for i...

}//end ModelInitialise. 

/** Update all R-D model parameters.
Update the model parameters for the R-D model (ln(md/Dmax), r), Mean Diff and the running
sums. The latest data must have been loaded into the fifo buffers prior to calling this
method. The values are updated on every StoreMeasurement() call.
@return : None.
*/
void RateControlImplQuad::ModelUpdate(void)
{
  /// Update ((md/Dmax), r) running sums.
  double x = (_distortionSamples.GetBuffer())[0];
  double y = (_coeffRateSamples.GetBuffer())[0];

  double x2 = x*x;
  double px2 = _prevDistortion*_prevDistortion;
  _Sx = UpdateRunningSum(_prevDistortion, x, _Sx);
  _Sy = UpdateRunningSum(_prevCoeffRate, y, _Sy);
  _Sxy = UpdateRunningSum(_prevCoeffRate / _prevDistortion, y / x, _Sxy);  ///< Inverse of distortion is required here.
  _Sx2 = UpdateRunningSum(px2, x2, _Sx2);

  /// Solve for a and b with least square error over the buffer frames.
  double bb = (((double)_numOfFrames*_Sy) - (_Sxy*_Sx)) / (((double)_numOfFrames*_Sx2) - (_Sx*_Sx));
  double aa = (_Sxy - (bb*_Sx)) / (double)_numOfFrames;

  /// TODO: Check the validity of aa and bb before assigning.

  _a = aa;
  _b = bb;

  /// TODO: Do performance measure as fitness to model.
  _Spr = UpdateRunningSum(_prevModelPredRate, (_modelPredRateSamples.GetBuffer())[0], _Spr);
  _Smr = UpdateRunningSum(_prevModelMismatchRate, (_modelMismatchRateSamples.GetBuffer())[0], _Smr);
  _modelFit = _Smr / _Spr;

  /// Update mean diff running sums.
  _SEy = UpdateRunningSum(_prevMeanDiff, (_meanDiffSamples.GetBuffer())[0], _SEy);
  _SEiy = 0.0;
  for (int i = 0; i < _numOfFrames; i++)
    _SEiy += (_numOfFrames - i)*(_meanDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
                                                                   /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SEiy, _SEy, &_a1, &_a2);

  /// Update model diff running sums.
  _SMy = UpdateRunningSum(_prevModelRateDiff, (_modelRateDiffSamples.GetBuffer())[0], _SMy);
  _SMiy = 0.0;
  for (int i = 0; i < _numOfFrames; i++)
    _SMiy += (_numOfFrames - i)*(_modelRateDiffSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
                                                                        /// Update linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SMiy, _SMy, &_m1, &_m2);

  /// Update total rate running sums.
  _Sbuff = UpdateRunningSum(_prevTotalRate, (_totalRateSamples.GetBuffer())[0], _Sbuff);

  /// Update header rate running sums.
  _SPy = UpdateRunningSum(_prevHeaderRate, (_headerRateSamples.GetBuffer())[0], _SPy);
  _SPiy = 0.0;
  for (int i = 0; i < _numOfFrames; i++)
    _SPiy += (_numOfFrames - i)*(_headerRateSamples.GetBuffer())[i]; ///< The sample time series are in reverse order in the fifo.
                                                                     /// Update header rate linear constants. Cramer's Rule.
  CramersRuleSoln(_SEi2, _SEi, _SEi, (double)_numOfFrames, _SPiy, _SPy, &_p1, &_p2);

}//end ModelUpdate.
========== END FILE: CodecUtils/RateControlImplQuad.cpp ==========

========== BEGIN FILE: CodecUtils/RateControlImplQuad.h ==========
Bundle entry: 114
Original bytes: 11192
Original SHA-256: 336d7c91b2547b91527dab332cf462c243a6651ace2da15bb845679e55f9a768
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RateControlImplQuad

TAG						: RCIQ

FILE NAME			: RateControlImplQuad.h

DESCRIPTION		: A class to hold an inverse quadratic model for the frame buffer rate rate control to
                match an average rate stream.

COPYRIGHT			: (c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RATECONTROLIMPLQUAD_H
#define _RATECONTROLIMPLQUAD_H

#pragma once

#include  <math.h>
#include  "IRateControl.h"
#include  "GeneralUtils/MeasurementTable.h"

//#define RCIQ_DUMP_RATECNTL  1
#define RCIQ_DUMP_FILENAME "C:/Users/KFerguson/Documents/Excel/VideoEvaluation/RateControlQuad_"	///< File name head only

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RateControlImplQuad : public IRateControl
{
public:
  RateControlImplQuad(void) 
  { _a = 15000.0; _b = -1.3; _numOfFrames = 0; 
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 16777216.0; _distLower = 1024.0; 
  }
  RateControlImplQuad(double modelparam_a, double modelparam_b) 
  { _a = modelparam_a; _b = modelparam_b; _numOfFrames = 0;  
    _rateUpper = 24.0; _rateLower = 0.0001; _distUpper = 16777216.0; _distLower = 1024.0;
  }
  virtual ~RateControlImplQuad() { Destroy(); }

/// IRateControl Interface methods.
public:
  int	Create(int numOfFrames);
  void	Destroy(void);
  int   GetFameBufferLength(void) { return(_numOfFrames); }
  void  SetRDLimits(double rateUpper, double rateLower, double distUpper, double distLower) 
    { _rateUpper = rateUpper; _rateLower = rateLower; _distUpper = distUpper; _distLower = distLower; }

  /// Pre-encoding: Apply the rate control model to predict the distortion from the target coeff rate.
  int PredictDistortion(double targetAvgRate, double rateLimit);
  /// Post-encoding: Add samples to the fifo buffers and hold the sample that is discarded.
  void StoreMeasurements(double rate, double coeffrate, double distortion, double mse, double mae);
  /// Return average rate across the buffer as the performance measure.
  double GetPerformanceMeasure(void) { return(_modelFit); }

  /// Is the data in the fifos valid.
  int ValidData(void) 
    { if(!_distortionSamples.Empty() && !_coeffRateSamples.Empty() && !_meanDiffSamples.Empty() && !_totalRateSamples.Empty() && !_headerRateSamples.Empty()) return(1); return(0); }
  /// Was the prediction calculation out of bounds?
  bool OutOfBounds(void) { return(_outOfBoundsFlag); }
  /// Who is the culprit?
  bool UpperDistortionOverflow(void) { return(_upperDistortionOverflowFlag); }
  bool LowerDistortionOverflow(void) { return(_lowerDistortionOverflowFlag); }
  bool UpperRateOverflow(void) { return(_upperRateOverflowFlag); }
  bool LowerRateOverflow(void) { return(_lowerRateOverflowFlag); }
  /// Reset the fifos to the last valid sample.
  void Reset(void);

  /// Utility functions.
  void Dump(const char* filename);  ///< Requires RCIQ_DUMP_RATECNTL to be set.
  void Dump(void);            ///< Requires RCIQ_DUMP_FILENAME to be defined.

/// Further implementation specific public methods.
public:

/// Private methods.
protected:
  /// These following group of methods must be called in this exact order because they operate
  /// on members that are interdependant.
  void PutMeanDiff(double meandiff, bool initialise) 
    { if(meandiff < 1.0) meandiff = 1.0;
      PutLinearMeasure(_meanDiffSamples, meandiff, &_prevMeanDiff, initialise); }
  void PutDistortion(double distortion, bool initialise) ///< Must only be called after a call to PutMeanDiff(). 
    { if(distortion < 1.0) distortion = 1.0;
      PutLinearMeasure(_distortionSamples, ((_meanDiffSamples.GetBuffer())[0]/distortion), &_prevDistortion, initialise); }
  void PutCoeffRate(double rate, bool initialise) 
    { PutLinearMeasure(_coeffRateSamples, rate, &_prevCoeffRate, initialise); } 
  void PutModelRateDiff(double ratediff, bool initialise) 
    { PutLinearMeasure(_modelRateDiffSamples, ratediff, &_prevModelRateDiff, initialise); }
  void PutTotalRate(double rate, bool initialise) 
    { PutLinearMeasure(_totalRateSamples, rate, &_prevTotalRate, initialise); }
  void PutHeaderRate(double headerRate, bool initialise) 
    { PutLinearMeasure(_headerRateSamples, headerRate, &_prevHeaderRate, initialise); }
  void PutPredRate(double rate, bool initialise) ///< Must only be called after PutDistortion() and PutHeaderRate().  
	{
	  double ds = (_distortionSamples.GetBuffer())[0];
	  double predRate = (_a*ds) + (_b*ds*ds) + (_headerRateSamples.GetBuffer())[0];
	  PutLinearMeasure(_modelPredRateSamples, predRate, &_prevModelPredRate, initialise);
	  double mismatch = fabs(rate - predRate);
	  PutLinearMeasure(_modelMismatchRateSamples, mismatch, &_prevModelMismatchRate, initialise);
	}

  double GetMostRecentCoeffRate(void) { return((_coeffRateSamples.GetBuffer())[0]); }
  double GetMostRecentTotalRate(void) { return((_totalRateSamples.GetBuffer())[0]); }
  double GetMostRecentHeaderRate(void) { return((_headerRateSamples.GetBuffer())[0]); }
  double GetMostRecentMeanDiff(void) { return((_meanDiffSamples.GetBuffer())[0]); }
  double GetMostRecentModelRateDiff(void) { return((_modelRateDiffSamples.GetBuffer())[0]); }

  /// Model equations.
  double ModelDistortion(double rate, double a, double b, double var) { return( (2.0*var*b)/(sqrt((a*a) + (4.0*b*rate)) - a) ); }
  double ModelRate(double distortion, double a, double b, double var) { return( ((a*var)/distortion) + ((b*var)/(distortion*distortion)) ); }
  double ModelMeanDifference(void);
  void   ModelInitialise(void);
  void   ModelUpdate(void);

/// Constant members.
public:

/// Common members.
protected:
	int		_numOfFrames;

  /// Clip the values of the rate and distortion to these limits.
  double    _rateUpper;
  double    _rateLower;
  double    _distUpper;
  double    _distLower;

  Fifo      _meanDiffSamples;      ///< Mean differnce between samples of frames.
  double    _prevMeanDiff;
  Fifo      _totalRateSamples;     ///< Stream rate including headers of frames.
  double    _prevTotalRate;
  Fifo      _coeffRateSamples;     ///< Coeff rate of frames.
  double    _prevCoeffRate;
  Fifo      _distortionSamples;    ///< (md/Dmax) for the frames.
  double    _prevDistortion;
  Fifo      _headerRateSamples;    ///< Header rate of frames.
  double    _prevHeaderRate;
  Fifo      _modelRateDiffSamples; ///< Model mismatch of frames.
  double    _prevModelRateDiff;
  double    _prevCoeffRatePred;
  /// Signal when the predicted values are not valid due to out of range errors. Use
  /// this signal to prevent contributions to the model data.
  bool      _outOfBoundsFlag;
  bool      _upperDistortionOverflowFlag;
  bool      _lowerDistortionOverflowFlag;
  bool      _upperRateOverflowFlag;
  bool      _lowerRateOverflowFlag;

  /// For the quadratic model x = md/Dmax and y = R. To update the constants
  /// a and b, quadratic roots are used to solve the linear equation for a least
  /// squares criterion curve fit. Running sums are used.
  double    _Sxy; ///< Sum(r.Dmax/md) Note the inverse of x here.
  double    _Sx2; ///< Sum(md^2/Dmax^2)
  double    _Sx;  ///< Sum(md/Dmax)
  double    _Sy;  ///< Sum(r)
  double    _a;   ///< Quadratic model "constants".
  double    _b;

  /// The prediction of Mean Diff requires a least squares criterion curve fit
  /// to a linear extrapolation model with constants a1 and a2.
  double    _SEi;
  double    _SEi2;
  double    _SEy;
  double    _SEiy;
  double    _a1;  ///< Linear model constants.
  double    _a2;

  /// Buffer rate control for average bit rate.
  double    _Sbuff;

  /// The prediction of frame header rate requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants p1 and p2. Uses _SEi and _SEi2 above.
  double    _SPy;
  double    _SPiy;
  double    _p1;  ///< Linear model constants.
  double    _p2;

  /// The prediction of model mismatch in rate requires a least mean squares criterion curve fit
  /// to a linear extrapolation model with constants m1 and m2. Uses _SEi and _SEi2 above.
  double    _SMy;
  double    _SMiy;
  double    _m1;  ///< Linear model constants.
  double    _m2;

  /// Measure the performance by the model accuracy.
  double    _modelFit;
  Fifo      _modelPredRateSamples;      ///< Model predicted rate is that defined by _a and _b.
  double    _prevModelPredRate;
  Fifo      _modelMismatchRateSamples;  ///< Abs diff between actual rate and model predicted rate.
  double    _prevModelMismatchRate;
  double    _Spr;                       ///< Fifo sum of pred model rate;
  double    _Smr;                       ///< Fifo sum of mismatch rate;

  /// Signalling parameters.
  double    _mseSignal;

  MeasurementTable  _RCTable;
  int               _RCTableLen;
  int               _RCTablePos;
#ifdef RCIQ_DUMP_RATECNTL
  double            _predMD;
  double            _MD;
  double            _predHeaderRate;
  double            _headerRate;
  double            _predDmax;
  double            _predCoeffRate;
  double            _coeffRate;
  double            _rate;
#endif
};// end class RateControlImplQuad.

#endif	// _RATECONTROLIMPLQUAD_H
========== END FILE: CodecUtils/RateControlImplQuad.h ==========

========== BEGIN FILE: CodecUtils/RawFileHandlerBase.cpp ==========
Bundle entry: 115
Original bytes: 6057
Original SHA-256: 409a36904ff5c35c86a7d3468f9f7cb56a36e62337b37ae01cf8f8e38ef5b8b1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RawFileHandlerBase

TAG						: H264RFH

FILE NAME			: RawFileHandlerBase.cpp

DESCRIPTION		: A base class for reading and writing raw data from and to
                a binary file. Derived classes must provide interpretation
                of headers and unit demarkations. 

COPYRIGHT			:	(c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#include <string.h>
#endif

#include <fstream>

#include "RawFileHandlerBase.h"

#define INITIAL_BUFFER_SIZE 40960

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
RawFileHandlerBase::RawFileHandlerBase(void)
{
  /// Buffer to hold the file data.
  _pFile      = NULL;
  _length     = 0;
  _currPos    = 0; ///< Current position in _pFile.
  _direction  = READ;
}//end constructor.

RawFileHandlerBase::~RawFileHandlerBase(void)
{
  Close();
}//end destructor.

/*
---------------------------------------------------------------------------
	Public interface methods.
---------------------------------------------------------------------------
*/
int RawFileHandlerBase::Open(const char* filename, int rw)
{
  /// Clear previous stuff.
  Close();

  strcpy(_filename, filename);
  _direction = rw;

  if(rw == READ)
  {
	  std::ifstream in1(filename, std::ios_base::in | std::ios_base::binary);
	  if (in1.is_open())
	  {
		  /// Get length of file:
		  in1.seekg (0, std::ios::end);
      std::streamoff len = in1.tellg();
		  in1.seekg (0, std::ios::beg);

      _length = static_cast<int>(len);
		  _pFile = new char[_length];

		  /// Read data as a block:
		  in1.read (_pFile, len);
		  in1.close();
    }//end if is_open...
    else
      return(0);
  }//end rw...
  else
  {
    /// For the WRITE case, the actual writing to file is delayed to the next call to Close().
    _length = INITIAL_BUFFER_SIZE;
    _pFile = new char[_length];
  }//end else...

  if(_pFile == NULL)
    return(0);

  return(1);
}//end Open.

/** Put an encoded unit onto the file stream buffer.
NOTE: The file stream buffer is only written to the file on a
call to Close(). Add this unit to the end of the stream buffer
references by the currPos.
@param length   : Bytes in the encoded unit.
@param unitLen  : Num of bytes to add.
@return         : Success = 1, Failure = 0.
*/
int RawFileHandlerBase::PutNextUnit(void* unit, int unitLen)
{
  if(_pFile == NULL)
    return(0);

  /// Grow the size of the file buffer if it overflows.
  if((_currPos + unitLen) >= _length)
  {
    /// Create a temp buffer.
    char* temp = NULL;
    temp = new char[_currPos+1];
    if(temp == NULL)
      return(0);
    memcpy(temp, _pFile, sizeof(char) * (_currPos + 1));

    /// Decide on how much to grow the buffer size with the default as double _length.
    if(unitLen > _length)
      _length = 4 * unitLen;
    else
      _length = 2 * _length;

    /// Create the bigger file buffer.
    delete[] _pFile;
    _pFile = NULL;
    _pFile = new char[_length];
    if(_pFile == NULL)
    {
      delete[] temp;
      _length = 0;
      return(0);
    }//end if _pFile...

    /// Copy the temp buffer into the new buffer.
    memcpy(_pFile, temp, sizeof(char) * (_currPos + 1));

    delete[] temp;
    temp = NULL;

  }//end if _currPos...

  /// Load the unit onto the end of the buffer.
  char* p = (char *)unit;
  for(int i = 0; i < unitLen; i++)
    _pFile[_currPos++] = p[i];

  return(1);
}//end PutNextUnit.

void RawFileHandlerBase::Close(void)
{
  /// File writing is delayed until a Close().
  if((_direction == WRITE)&&(_currPos > 0))
  {
    std::ofstream out1(_filename, std::ios_base::out | std::ios_base::binary);
    if(out1.is_open())
    {
      out1.write(_pFile, _currPos);
      out1.close();
      _currPos = 0;
    }//end if is_open...
  }//end if _direction...

  if(_pFile != NULL)
    delete[] _pFile;
  _pFile    = NULL;
  _length   = 0;
  _currPos  = 0;
}//end Close.

========== END FILE: CodecUtils/RawFileHandlerBase.cpp ==========

========== BEGIN FILE: CodecUtils/RawFileHandlerBase.h ==========
Bundle entry: 116
Original bytes: 3428
Original SHA-256: 8cff2fd8f8abfc59e5324ee1278580536af0db6e1ad421032957e8772cc4a424
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RawFileHandlerBase

TAG						: RFHB

FILE NAME			: RawFileHandlerBase.h

DESCRIPTION		: A base class for reading and writing raw data from and to
                a binary file. Derived classes must provide interpretation
                of headers and unit demarkations.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _RAWFILEHANDLERBASE_H
#define _RAWFILEHANDLERBASE_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RawFileHandlerBase
{
public:
	RawFileHandlerBase(void);
	virtual ~RawFileHandlerBase(void);

/// Public constants.
public:
	/// Read or write parameter for Open() method.
	static const int READ	    = 0;
	static const int WRITE    = 1;

/// Public interface.
public:

  virtual int   Open(const char* filename, int rw);
  virtual void  Close(void);

  /** Get a ptr to the head of the next data unit.
  Return the ptr and the length of the next frame/unit
  of data after the currPos.
  @param length : Bytes in the encoded unit
  @return       : Ptr to the head of the unit.
  */
  virtual void* GetNextUnit(int* unitLen) { return(NULL); }
  virtual int   PutNextUnit(void* unit, int unitLen);

/// Private members.
protected:

  /// Buffer to hold the file data.
  char* _pFile;
  int   _length;
  int   _currPos; ///< Current position in _pFile.
  char  _filename[256];
  int   _direction; /// READ or WRITE.

};// end class RawFileHandlerBase.

#endif	//_RAWFILEHANDLERBASE_H
========== END FILE: CodecUtils/RawFileHandlerBase.h ==========

========== BEGIN FILE: CodecUtils/RunBeforeH264VlcDecoder.cpp ==========
Bundle entry: 117
Original bytes: 10200
Original SHA-256: 4ba9e3a6f890ec43ed30baa8e46a02b5c5ea48c5e99597ed7a94309352c7eaba
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RunBeforeH264VlcDecoder

TAG						: RBH264VD

FILE NAME			: RunBeforeH264VlcDecoder.cpp

DESCRIPTION		: A run before Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.10 page 206. The 
								zero coeffs left defines which vlc array to use. This 
								implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "RunBeforeH264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
RunBeforeH264VlcDecoder::RunBeforeH264VlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

RunBeforeH264VlcDecoder::~RunBeforeH264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode run before - zeros left symbols from the bit stream.
The first 2 param symbols represent run before and zeros left, respectively. The 
zeros left is an input that selects the appropriate vlc array for the run before
decoding. For fast implementation the tree splitting is done in the code.
@param bsr			: Bit stream to get from.
@param symbol1	: Returned run before for this coeff.
@param symbol2	: Zeros left for this block.
@return					: Num of bits extracted.
*/
int	RunBeforeH264VlcDecoder::Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
{
	int zerosLeft	= *symbol2;	///< Used as an input.

	/// Reset bits extracted.
  _numCodeBits	= 0;
	int rB				= 0;

	/// Select the method depending on the total number of coeffs.
	switch(zerosLeft)
	{
		case 1:
			{
				if(bsr->Read())	///< 1
					rB = 0;
				else						///< 0
					rB = 1;
				_numCodeBits = 1;
			}//end case 1...
			break;
		case 2:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; rB = 0;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; rB = 1;
					}//end if 01...
					else						///< 00
					{
						_numCodeBits = 2; rB = 2;
					}//end else 00...
				}//end else 0...
			}//end case 2...
			break;
		case 3:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
						rB = 0;
					else						///< 10
						rB = 1;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
						rB = 2;
					else						///< 00
						rB = 3;
				}//end else 0...
				_numCodeBits = 2;
			}//end case 3...
			break;
		case 4:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						_numCodeBits = 2; rB = 0;
					}//end if 11...
					else						///< 10
					{
						_numCodeBits = 2; rB = 1;
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; rB = 2;
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; rB = 3;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; rB = 4;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 4...
			break;
		case 5:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						_numCodeBits = 2; rB = 0;
					}//end if 11...
					else						///< 10
					{
						_numCodeBits = 2; rB = 1;
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						if(bsr->Read())	///< 011
						{
							_numCodeBits = 3; rB = 2;
						}//end if 011...
						else						///< 010
						{
							_numCodeBits = 3; rB = 3;
						}//end else 010...
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; rB = 4;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; rB = 5;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 5...
			break;
		case 6:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						_numCodeBits = 2; rB = 0;
					}//end if 11...
					else						///< 10
					{
						if(bsr->Read())	///< 101
						{
							_numCodeBits = 3; rB = 5;
						}//end if 101...
						else						///< 100
						{
							_numCodeBits = 3; rB = 6;
						}//end else 100...
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						if(bsr->Read())	///< 011
						{
							_numCodeBits = 3; rB = 3;
						}//end if 011...
						else						///< 010
						{
							_numCodeBits = 3; rB = 4;
						}//end else 010...
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; rB = 2;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; rB = 1;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 6...
			break;
		default:	///< Greater than 6.
			{
				if(zerosLeft > 6)
				{
					if(bsr->Read())	///< 1
					{
						if(bsr->Read())	///< 11
						{
							if(bsr->Read())	///< 111
							{
								_numCodeBits = 3; rB =0 ;
							}//end if 111...
							else						///< 110
							{
								_numCodeBits = 3; rB = 1;
							}//end else 110...
						}//end if 11...
						else						///< 10
						{
							if(bsr->Read())	///< 101
							{
								_numCodeBits = 3; rB = 2;
							}//end if 101...
							else						///< 100
							{
								_numCodeBits = 3; rB = 3;
							}//end else 100...
						}//end else 10...
					}//end if 1...
					else						///< 0
					{
						if(bsr->Read())	///< 01
						{
							if(bsr->Read())	///< 011
							{
								_numCodeBits = 3; rB = 4;
							}//end if 011...
							else						///< 010
							{
								_numCodeBits = 3; rB = 5;
							}//end else 010...
						}//end if 01...
						else						///< 00
						{
							if(bsr->Read())	///< 001
							{
								_numCodeBits = 3; rB = 6;
							}//end if 001...
							else						///< 000
							{
								if(bsr->Read())	///< 0001
								{
									_numCodeBits = 4; rB = 7;
								}//end if 0001...
								else						///< 0000
								{
									if(bsr->Read())	///< 0000 1
									{
										_numCodeBits = 5; rB = 8;
									}//end if 0000 1...
									else						///< 0000 0
									{
										if(bsr->Read())	///< 0000 01
										{
											_numCodeBits = 6; rB = 9;
										}//end if 0000 01...
										else						///< 0000 00
										{
											if(bsr->Read())	///< 0000 001
											{
												_numCodeBits = 7; rB = 10;
											}//end if 0000 001...
											else						///< 0000 000
											{
												if(bsr->Read())	///< 0000 0001
												{
													_numCodeBits = 8; rB = 11;
												}//end if 0000 0001...
												else						///< 0000 0000
												{
													if(bsr->Read())	///< 0000 0000 1
													{
														_numCodeBits = 9; rB = 12;
													}//end if 0000 0000 1...
													else						///< 0000 0000 0
													{
														if(bsr->Read())	///< 0000 0000 01
														{
															_numCodeBits = 10; rB = 13;
														}//end if 0000 0000 01...
														else						///< 0000 0000 00
														{
															if(bsr->Read())	///< 0000 0000 001
															{
																_numCodeBits = 11; rB = 14;
															}//end if 0000 0000 001...
														}//end else 0000 0000 00...
													}//end else 0000 0000 0...
												}//end else 0000 0000...
											}//end else 0000 000...
										}//end else 0000 00...
									}//end else 0000 0...
								}//end else 0000...
							}//end else 000...
						}//end else 00...
					}//end else 0...
				}//end if zerosLeft...
			}//end case >6...
			break;
	}//end switch zerosLeft...

	/// Load 'em up.
	*symbol1 = rB;

  return(_numCodeBits);
}//end Decode2.


========== END FILE: CodecUtils/RunBeforeH264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/RunBeforeH264VlcDecoder.h ==========
Bundle entry: 118
Original bytes: 3339
Original SHA-256: 3de59f2bafb0c6051f2af36cfff9aa1094dd882fe65652029dd60122319c1d16
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RunBeforeH264VlcDecoder

TAG						: RBH264VD

FILE NAME			: RunBeforeH264VlcDecoder.h

DESCRIPTION		: A run before Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.10 page 206. The 
								zero coeffs left defines which vlc array to use. This 
								implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RUNBEFOREH264VLCDECODER_H
#define _RUNBEFOREH264VLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RunBeforeH264VlcDecoder : public IVlcDecoder
{
public:
	RunBeforeH264VlcDecoder();
	virtual ~RunBeforeH264VlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Decode(IBitStreamReader* bsr) { _numCodeBits = 0; return(0); } 

	/// Optional interface implementation.
	/// The 2 symbols represent run before (output) and zeros left (input), respectively.
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2);

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class RunBeforeH264VlcDecoder.

#endif	// _RUNBEFOREH264VLCDECODER_H
========== END FILE: CodecUtils/RunBeforeH264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/RunBeforeH264VlcEncoder.cpp ==========
Bundle entry: 119
Original bytes: 5328
Original SHA-256: a9ff1f99f4a7585b5146fde87adcd345c6a0b6c5651a7cf654764238f58546c1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RunBeforeH264VlcEncoder

TAG						: RBH264VE

FILE NAME			: RunBeforeH264VlcEncoder.cpp

DESCRIPTION		: A run before Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.10 page 206. The 
								zero coeffs left defines which vlc array to use. This 
								implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "RunBeforeH264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
RunBeforeH264VlcEncoder::RunBeforeH264VlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
}//end constructor.

RunBeforeH264VlcEncoder::~RunBeforeH264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode total zeros - total coeffs symbols.
The 2 param symbols represent run before and zeros left, respectively, and 
are encoded with the number of bits returned. The _numCodeBits and _bitCode 
members are set accordingly.
@param symbol1	:	Run before. 
@param symbol2	: Zeros left.
@return					: Num of bits in the codeword.
*/
int	RunBeforeH264VlcEncoder::Encode2(int symbol1, int symbol2)
{
	int runBefore	= symbol1;
	int zerosLeft	= symbol2;

	if(zerosLeft > 6)	///< Use the last column for all greater than 6.
		zerosLeft = 7;

	_bitCode			= table[runBefore][zerosLeft].codeWord;
	_numCodeBits	= table[runBefore][zerosLeft].numBits;

	return(_numCodeBits);
}// end Encode2.


/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const RBH264VE_VlcCodeType RunBeforeH264VlcEncoder::table[15][8] = 
{///<	0				 1				2				 3				4				 5				6				 >6 = zerosLeft.
	{ { 0, 0}, { 1, 1}, { 1, 1}, { 2, 3}, { 2, 3}, { 2, 3}, { 2, 3}, { 3, 7} }, ///< 0 = runBefore.
	{ { 0, 0}, { 1, 0}, { 2, 1}, { 2, 2}, { 2, 2}, { 2, 2}, { 3, 0}, { 3, 6} }, ///< 1
	{ { 0, 0}, { 0, 0}, { 2, 0}, { 2, 1}, { 2, 1}, { 3, 3}, { 3, 1}, { 3, 5} }, ///< 2
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 2, 0}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4} }, ///< 3
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 3, 0}, { 3, 1}, { 3, 2}, { 3, 3} }, ///< 4
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 3, 0}, { 3, 5}, { 3, 2} }, ///< 5
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 3, 4}, { 3, 1} }, ///< 6
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 4, 1} }, ///< 7
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 5, 1} }, ///< 8
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 6, 1} }, ///< 9
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 7, 1} }, ///< 10
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 8, 1} }, ///< 11
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 9, 1} }, ///< 12
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {10, 1} }, ///< 13
	{ { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {11, 1} }	///< 14
};


========== END FILE: CodecUtils/RunBeforeH264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/RunBeforeH264VlcEncoder.h ==========
Bundle entry: 120
Original bytes: 3727
Original SHA-256: a7977fdd79b6f40fc6b7b8e6b7b06b437da812e01e41e24766d03268ac0c09da
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: RunBeforeH264VlcEncoder

TAG						: RBH264VE

FILE NAME			: RunBeforeH264VlcEncoder.h

DESCRIPTION		: A run before Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.10 page 206. The 
								zero coeffs left defines which vlc array to use. This 
								implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _RUNBEFOREH264VLCENCODER_H
#define _RUNBEFOREH264VLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Type definitions.
---------------------------------------------------------------------------
*/
typedef struct _RBH264VE_VlcCodeType
{
  int		numBits;	///< Num of bits in code word.
  int		codeWord;	///< Code word bit representation.
} RBH264VE_VlcCodeType;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class RunBeforeH264VlcEncoder : public IVlcEncoder
{
public:
	RunBeforeH264VlcEncoder(void);
	virtual ~RunBeforeH264VlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface implementation.
	/// The 2 symbols represent run before and zeros left, respectively.
	virtual int	Encode2(int symbol1, int symbol2);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

	/// Constants of table sets.
	static const RBH264VE_VlcCodeType table[15][8];

};// end class RunBeforeH264VlcEncoder.

#endif	// end _RUNBEFOREH264VLCENCODER_H.
========== END FILE: CodecUtils/RunBeforeH264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/SeqParamSetH264.cpp ==========
Bundle entry: 121
Original bytes: 12364
Original SHA-256: b17cfc5bf3ec0f486db4468214fcd9d2d1d9978d7ad067c93d69f148d4043585
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: SeqParamSetH264

TAG						: SPSH264

FILE NAME			: SeqParamSetH264.cpp

DESCRIPTION		: A class to hold H.264 sequence parameter set data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2013 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "SeqParamSetH264.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
SeqParamSetH264::SeqParamSetH264(int seqParamSetId)
{
  int i;

	_seq_parameter_set_id										= seqParamSetId;	///< The index for this definition of sequence params [0..31].

	_profile_idc														= 66;							///< Baseline profile = 66.
	_constraint_set0_flag										= 0;							///< = 0.
	_constraint_set1_flag										= 0;							///< = 0.
	_constraint_set2_flag										= 0;							///< = 0.
	_constraint_set3_flag										= 0;							///< = 0.
	_level_idc															= 20;							///< = 20 (Level num = 2, calculated as 10 x level num).

	_chroma_format_idc											= 1;							///< Range = [0..3]. When not present = 1 (4:2:0).
	_residual_colour_transform_flag					= 0;							///< = 0.
	_bit_depth_luma_minus8									= 0;							///< Range = [0..4]. When not present = 0 (8 bits/lum component).
	_bit_depth_chroma_minus8								= 0;							///< Range = [0..4]. When not present = 0 (8 bits/chr component).
	_qpprime_y_zero_transform_bypass_flag		= 0;							///< If QP = 0, this flag indicates bypassing the transform process. When not present = 0.

	_seq_scaling_matrix_present_flag				= 0;							///< = 0. No scaling matrices for baseline profile. Indicates existence of _seq_scaling_list_present_flag flags.
	for(i = 0; i < 8; i++)                              			///< if _seq_scaling_matrix_present_flag, these indicate lists not present/present (0/1).
	  _seq_scaling_list_present_flag[i]     = 0;
  /// Not initialised _scaling_list_4x4[6][16], _use_default_scaling_matrix_4x4_flag[6], _scaling_list_8x8[2][64], _use_default_scaling_matrix_8x8_flag[2]

	_log2_max_frame_num_minus4							= 12;							///< Range = [0..12]. MaxFrameNum = 2^(_log2_max_frame_num_minus4 + 4) for slice _frame_num derivations.

	_pic_order_cnt_type											= 2;							///< Range = [0..2]. Decoding technique selected for mapping coding order count to frame num. [2 = 1 to 1 mapping]
	_log2_max_pic_order_cnt_lsb_minus4			= 0;							///< For B-Slice decoding.  There are no B-Slices in the baseline profile.
	_delta_pic_order_always_zero_flag				= 0;							///< For B-Slice decoding.
	_offset_for_non_ref_pic									= 0;							///< For B-Slice decoding.
	_offset_for_top_to_bottom_field					= 0;							///< For B-Slice decoding.
	_num_ref_frames_in_pic_order_cnt_cycle	= 0;							///< For B-Slice decoding.
	/// Not initialised _offset_for_ref_frame[256];						///< For B-Slice decoding.

	_num_ref_frames													= 1;							///< Max num of short-term and long-term ref frames.
	_gaps_in_frame_num_value_allowed_flag		= 0;							///< Indicates allowed values of slice _frame_num.

	_pic_width_in_mbs_minus1								= 21;							///< 16*(21+1)=352 Width of decoded pic in units of macroblocks. Derive lum and chr pic width from this variable.
	_pic_height_in_map_units_minus1					= 17;							///< 16*(17+1)=288 Map units are 2 macroblocks for fields and 1 for frames. Derive lum and chr pic height from this variable.

	_frame_mbs_only_flag										= 1;							///< = 1 (baseline profile). fields/frames = 0/1.
	_mb_adaptive_frame_field_flag						= 0;							///< Indicates switching between frame and field macroblocks. When not present = 0.

	_direct_8x8_inference_flag							= 0;							///< Methods for B-Slice motion vector decoding.  There are no B-Slices in the baseline profile.

	_frame_cropping_flag										= 0;							///< Indicates that the cropping params below follow in the stream.
	_frame_crop_left_offset									= 0;							///< In frame coordinate units.
	_frame_crop_right_offset								= 0;							///< In frame coordinate units.
	_frame_crop_top_offset									= 0;							///< In frame coordinate units.
	_frame_crop_bottom_offset								= 0;							///< In frame coordinate units.

	_vui_parameters_present_flag						= 0;							///< vui parameters follow.

}//end constructor.

SeqParamSetH264::~SeqParamSetH264(void)
{
}//end destructor.

void SeqParamSetH264::CopyProxy(SeqParamSetH264* me, SeqParamSetH264* from)
{
  int i;

	me->_seq_parameter_set_id	                  = from->_seq_parameter_set_id;

	me->_profile_idc														= from->_profile_idc;
	me->_constraint_set0_flag										= from->_constraint_set0_flag;
	me->_constraint_set1_flag										= from->_constraint_set1_flag;
	me->_constraint_set2_flag										= from->_constraint_set2_flag;
	me->_constraint_set3_flag										= from->_constraint_set3_flag;
	me->_level_idc															= from->_level_idc;

	me->_chroma_format_idc											= from->_chroma_format_idc;
	me->_residual_colour_transform_flag					= from->_residual_colour_transform_flag;
	me->_bit_depth_luma_minus8									= from->_bit_depth_luma_minus8;
	me->_bit_depth_chroma_minus8								= from->_bit_depth_chroma_minus8;
	me->_qpprime_y_zero_transform_bypass_flag		= from->_qpprime_y_zero_transform_bypass_flag;

	me->_seq_scaling_matrix_present_flag				= from->_seq_scaling_matrix_present_flag;
  for(i = 0; i < 8; i++)
	  me->_seq_scaling_list_present_flag[i]     = from->_seq_scaling_list_present_flag[i];
  /// Not copied _scaling_list_4x4[6][16], _use_default_scaling_matrix_4x4_flag[6], _scaling_list_8x8[2][64], _use_default_scaling_matrix_8x8_flag[2]

	me->_log2_max_frame_num_minus4							= from->_log2_max_frame_num_minus4;

	me->_pic_order_cnt_type											= from->_pic_order_cnt_type;
	me->_log2_max_pic_order_cnt_lsb_minus4			= from->_log2_max_pic_order_cnt_lsb_minus4;
	me->_delta_pic_order_always_zero_flag				= from->_delta_pic_order_always_zero_flag;
	me->_offset_for_non_ref_pic									= from->_offset_for_non_ref_pic;
	me->_offset_for_top_to_bottom_field					= from->_offset_for_top_to_bottom_field;
	me->_num_ref_frames_in_pic_order_cnt_cycle	= from->_num_ref_frames_in_pic_order_cnt_cycle;
	/// Not copied _offset_for_ref_frame[256];

	me->_num_ref_frames													= from->_num_ref_frames;
	me->_gaps_in_frame_num_value_allowed_flag		= from->_gaps_in_frame_num_value_allowed_flag;

	me->_pic_width_in_mbs_minus1								= from->_pic_width_in_mbs_minus1;
	me->_pic_height_in_map_units_minus1					= from->_pic_height_in_map_units_minus1;

	me->_frame_mbs_only_flag										= from->_frame_mbs_only_flag;
	me->_mb_adaptive_frame_field_flag						= from->_mb_adaptive_frame_field_flag;

	me->_direct_8x8_inference_flag							= from->_direct_8x8_inference_flag;

	me->_frame_cropping_flag										= from->_frame_cropping_flag;
	me->_frame_crop_left_offset									= from->_frame_crop_left_offset;
	me->_frame_crop_right_offset								= from->_frame_crop_right_offset;
	me->_frame_crop_top_offset									= from->_frame_crop_top_offset;
	me->_frame_crop_bottom_offset								= from->_frame_crop_bottom_offset;

	me->_vui_parameters_present_flag						= from->_vui_parameters_present_flag;

}//end CopyProxy.

int SeqParamSetH264::EqualsProxy(SeqParamSetH264* me, SeqParamSetH264* to)
{
	if( (me->_seq_parameter_set_id	              != to->_seq_parameter_set_id)||

	    (me->_profile_idc													!= to->_profile_idc)||
	    (me->_constraint_set0_flag								!= to->_constraint_set0_flag)||
	    (me->_constraint_set1_flag								!= to->_constraint_set1_flag)||
	    (me->_constraint_set2_flag								!= to->_constraint_set2_flag)||
	    (me->_constraint_set3_flag								!= to->_constraint_set3_flag)||
	    (me->_level_idc														!= to->_level_idc) )
        return(0);

	if( (me->_chroma_format_idc										!= to->_chroma_format_idc)||
	    (me->_residual_colour_transform_flag			!= to->_residual_colour_transform_flag)||
	    (me->_bit_depth_luma_minus8								!= to->_bit_depth_luma_minus8)||
	    (me->_bit_depth_chroma_minus8							!= to->_bit_depth_chroma_minus8)||
	    (me->_qpprime_y_zero_transform_bypass_flag != to->_qpprime_y_zero_transform_bypass_flag) )
        return(0);

	if(me->_seq_scaling_matrix_present_flag				!= to->_seq_scaling_matrix_present_flag)
    return(0);
	/// Not compared _seq_scaling_list_present_flag[8]
  /// Not compared _scaling_list_4x4[6][16], _use_default_scaling_matrix_4x4_flag[6], _scaling_list_8x8[2][64], _use_default_scaling_matrix_8x8_flag[2]

	if(me->_log2_max_frame_num_minus4							!= to->_log2_max_frame_num_minus4)
    return(0);

	if( (me->_pic_order_cnt_type									!= to->_pic_order_cnt_type)||
	    (me->_log2_max_pic_order_cnt_lsb_minus4		!= to->_log2_max_pic_order_cnt_lsb_minus4)||
	    (me->_delta_pic_order_always_zero_flag		!= to->_delta_pic_order_always_zero_flag)||
	    (me->_offset_for_non_ref_pic							!= to->_offset_for_non_ref_pic)||
	    (me->_offset_for_top_to_bottom_field			!= to->_offset_for_top_to_bottom_field)||
	    (me->_num_ref_frames_in_pic_order_cnt_cycle	!= to->_num_ref_frames_in_pic_order_cnt_cycle) )
        return(0);
	/// Not initialised _offset_for_ref_frame[256];

	if( (me->_num_ref_frames												!= to->_num_ref_frames)||
	    (me->_gaps_in_frame_num_value_allowed_flag	!= to->_gaps_in_frame_num_value_allowed_flag)||

	    (me->_pic_width_in_mbs_minus1								!= to->_pic_width_in_mbs_minus1)||
	    (me->_pic_height_in_map_units_minus1				!= to->_pic_height_in_map_units_minus1)||

	    (me->_frame_mbs_only_flag										!= to->_frame_mbs_only_flag)||
	    (me->_mb_adaptive_frame_field_flag					!= to->_mb_adaptive_frame_field_flag)||

	    (me->_direct_8x8_inference_flag							!= to->_direct_8x8_inference_flag) )
        return(0);

	if( (me->_frame_cropping_flag										!= to->_frame_cropping_flag)||
	    (me->_frame_crop_left_offset								!= to->_frame_crop_left_offset)||
	    (me->_frame_crop_right_offset								!= to->_frame_crop_right_offset)||
	    (me->_frame_crop_top_offset									!= to->_frame_crop_top_offset)||
	    (me->_frame_crop_bottom_offset							!= to->_frame_crop_bottom_offset) )
        return(0);

	if(me->_vui_parameters_present_flag						  != to->_vui_parameters_present_flag)
    return(0);

  return(1);
}//end EqualsProxy.


========== END FILE: CodecUtils/SeqParamSetH264.cpp ==========

========== BEGIN FILE: CodecUtils/SeqParamSetH264.h ==========
Bundle entry: 122
Original bytes: 6700
Original SHA-256: 05d0295506cc24bf080642d09f1c5f7853d10778bfb12f2b137cebaf8ff01af2
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: SeqParamSetH264

TAG						: SPSH264

FILE NAME			: SeqParamSetH264.h

DESCRIPTION		: A class to hold H.264 sequence parameter set data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2015 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _SEQPARAMSETH264_H
#define _SEQPARAMSETH264_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class SeqParamSetH264
{
public:
	SeqParamSetH264(int seqParamSetId = 0);
	virtual ~SeqParamSetH264(void);

/// Public operators.
public:
  void Copy(SeqParamSetH264* from)  { CopyProxy(this, from); }
  int Equals(SeqParamSetH264* to)   { return(EqualsProxy(this, to)); }
  int GetPicWidth(void)             { return( (_pic_width_in_mbs_minus1+1)*16 ); }
  int GetPicHeight(void)            { return( (_pic_height_in_map_units_minus1+1)*16 );}

/// Private operators.
private:
  static void CopyProxy(SeqParamSetH264* me, SeqParamSetH264* from);
  static int EqualsProxy(SeqParamSetH264* me, SeqParamSetH264* to);

/// Public constants.
public:

/// Public members.

	/// Only the baseline profile at level 2 is used in this implemention. Therefore, most 
	/// of these parameters are are constant and not used.
public:
	int _seq_parameter_set_id;										///< The index for this definition of sequence params [0..31].

	int _profile_idc;															///< Baseline profile = 66.
	int _constraint_set0_flag;										///< = 0.
	int _constraint_set1_flag;										///< = 0.
	int _constraint_set2_flag;										///< = 0.
	int _constraint_set3_flag;										///< = 0.
	int _level_idc;																///< = 20 (Level num = 2, calculated as 10 x level num).

	int _chroma_format_idc;												///< Range = [0..3]. When not present = 1 (4:2:0).
	int _residual_colour_transform_flag;					///< = 0.
	int _bit_depth_luma_minus8;										///< Range = [0..4]. When not present = 0 (8 bits/lum component).
	int _bit_depth_chroma_minus8;									///< Range = [0..4]. When not present = 0 (8 bits/chr component).
	int _qpprime_y_zero_transform_bypass_flag;		///< If QP = 0, this flag indicates bypassing the transform process. When not present = 0.

	int _seq_scaling_matrix_present_flag;					///< = 0. No scaling matrices for baseline profile. Indicates existence of _seq_scaling_list_present_flag flags.
	int _seq_scaling_list_present_flag[8];				///< if _seq_scaling_matrix_present_flag, these indicate lists not present/present (0/1).
  int _scaling_list_4x4[6][16];
  int _use_default_scaling_matrix_4x4_flag[6];
  int _scaling_list_8x8[2][64];
  int _use_default_scaling_matrix_8x8_flag[2];

	int _log2_max_frame_num_minus4;								///< Range = [0..12]. MaxFrameNum = 2^(_log2_max_frame_num_minus4 + 4) for slice _frame_num derivations.

	int _pic_order_cnt_type;											///< Range = [0..2]. Decoding technique selected for mapping coding order count to frame num.
	int _log2_max_pic_order_cnt_lsb_minus4;				///< For B-Slice decoding.  Range = [0..12]. There are no B-Slices in the baseline profile.
	int _delta_pic_order_always_zero_flag;				///< For B-Slice decoding.
	int _offset_for_non_ref_pic;									///< For B-Slice decoding.
	int _offset_for_top_to_bottom_field;					///< For B-Slice decoding.
	int _num_ref_frames_in_pic_order_cnt_cycle;		///< For B-Slice decoding.
	int _offset_for_ref_frame[256];								///< For B-Slice decoding.

	int _num_ref_frames;													///< Max num of short-term and long-term ref frames used for prediction.
	int _gaps_in_frame_num_value_allowed_flag;		///< Indicates allowed values of slice _frame_num.

	int _pic_width_in_mbs_minus1;									///< Width of decoded pic in units of macroblocks. Derive lum and chr pic width from this variable.
	int _pic_height_in_map_units_minus1;					///< Map units are 2 macroblocks for fields and 1 for frames. Derive lum and chr pic height from this variable.

	int _frame_mbs_only_flag;											///< = 1 (baseline profile). fields/frames = 0/1.
	int _mb_adaptive_frame_field_flag;						///< Indicates switching between frame and field macroblocks. When not present = 0.

	int _direct_8x8_inference_flag;								///< Methods for B-Slice motion vector decoding.  There are no B-Slices in the baseline profile.

	int _frame_cropping_flag;											///< Indicates that the cropping params below follow in the stream.
	int _frame_crop_left_offset;									///< In frame coordinate units.
	int _frame_crop_right_offset;									///< In frame coordinate units.
	int _frame_crop_top_offset;										///< In frame coordinate units.
	int _frame_crop_bottom_offset;								///< In frame coordinate units.

	int _vui_parameters_present_flag;							///< vui parameters follow.

};// end class SeqParamSetH264.

#endif	//_SEQPARAMSETH264_H
========== END FILE: CodecUtils/SeqParamSetH264.h ==========

========== BEGIN FILE: CodecUtils/SliceHeaderH264.cpp ==========
Bundle entry: 123
Original bytes: 5179
Original SHA-256: 8377495f9c1a98f5d2241eb8af29c9f7031cd25b47325a3fcdf7087363652db2
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: SliceHeaderH264

TAG						: SHH264

FILE NAME			: SliceHeaderH264.cpp

DESCRIPTION		: A class to hold H.264 slice header data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "SliceHeaderH264.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
SliceHeaderH264::SliceHeaderH264(void)
{
	_id																	= 0;	///< Slice number in a picture.

	_first_mb_in_slice									= 0;	///< The raster ordered first macroblock number that starts this slice.
	_type																= 0;	///< Defined by the slice type constants.
	_pic_parameter_set_id								= 0;	///< Parameter set to use in this slice.
	_frame_num													= 0;	///< Frame number from the last IDR frame.

	_field_pic_flag											= 0;	///< When present: 1 = slice is a field, 0 (default) = slice is a frame.
	_bottom_field_flag									= 0;	///< When present: 1 = slice is part of bottom field, 0 (default) = top field.
	_idr_pic_id													= 0;	///< For NAL unit = 5, increments for consecutive idr pictures, identifies which pic an I-slice belongs to.
	_pic_order_cnt_lsb									= 0;	///< Modulo pic order count for top field of frame or for a coded field.
	_delta_pic_order_cnt_bottom					= 0;	///< Pic order count difference between bottom and top field of a frame.
	_delta_pic_order_cnt[0]							= 0;	///< Pic order count difference from expected order count of the top/bottom field (default = 0);
	_delta_pic_order_cnt[1]							= 0;
	_redundant_pic_cnt									= 0;	///< 0 = slice belongs to primary coded pic, greater than 0 = redundant coded pic number.

	_direct_spatial_mv_pred_flag				= 0;	///< For B-slices, method used for decoding motion vectors.
	_num_ref_idx_active_override_flag		= 0;	///< Activates/deactivates following members.
	_num_ref_idx_l0_active_minus1				= 0;
	_num_ref_idx_l1_active_minus1				= 0;

	_ref_pic_list_reordering_flag_l0		= 0;	///< Signals the reordering of the pictures in list 0.
	_reordering_of_pic_nums_idc					= 0;
	_abs_diff_pic_num_minus1						= 0;
	_long_term_pic_num									= 0;

	_no_output_of_prior_pics_flag				= 0;
	_long_term_reference_flag						= 0;	///< Mark this IDR picture slice for long term reference.
	_adaptive_ref_pic_marking_mode_flag = 0;	
	
	_cabac_init_idc											= 0;	///< Index for initialisation table for arethmetic entropy coding.

	_qp 																= 0;	///< QP used in this slice.
	_qp_delta														= 0;	///< Change in QP from the previous slice.

	_sp_for_switch_flag									= 0;	///< Specifies decoding process for SP-Slices.
	_qs_delta														= 0;	///< Change in QS from previous slice.

	_disable_deblocking_filter_idc			= 0;	///< Partial disabling of deblocking filter. (0 = default.)
	_alpha_c0_offset_div2								= 0;	///< Offset in alpha and tC0 filter tables.
	_beta_offset_div2										= 0;	///< Offset in beta filter table.

	_group_change_cycle									= 0;	///< Slice group map unit change.
}//end constructor.

SliceHeaderH264::~SliceHeaderH264(void)
{
}//end destructor.

========== END FILE: CodecUtils/SliceHeaderH264.cpp ==========

========== BEGIN FILE: CodecUtils/SliceHeaderH264.h ==========
Bundle entry: 124
Original bytes: 6113
Original SHA-256: d712c14310ac3bcd36ad24d57e2d708a13a12aed117826fd31f1357d68085bd7
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: SliceHeaderH264

TAG						: SHH264

FILE NAME			: SliceHeaderH264.h

DESCRIPTION		: A class to hold H.264 slice header data for use in the 
								H264v2Codec class.

COPYRIGHT			:	(c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _SLICEHEADERH264_H
#define _SLICEHEADERH264_H

#pragma once

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class SliceHeaderH264
{
public:
	SliceHeaderH264(void);
	virtual ~SliceHeaderH264(void);

/// Public constants.
public:
	/// Slice types for _slice_type member.
	static const int P_Slice	    = 0;
	static const int B_Slice	    = 1;
	static const int I_Slice	    = 2;
	static const int SP_Slice     = 3;
	static const int SI_Slice     = 4;
	static const int P_Slice_All	= 5;
	static const int B_Slice_All	= 6;
	static const int I_Slice_All	= 7;
	static const int SP_Slice_All = 8;
	static const int SI_Slice_All = 9;

/// Public members.
public:
	int _id;																///< Slice number in a picture. Macroblocks are asigned to this id. (Not in stream.)

	int _first_mb_in_slice;									///< The raster ordered first macroblock number that starts this slice.
	int _type;															///< Defined by the slice type constants.
	int _pic_parameter_set_id;							///< Parameter set to use in this slice.
	int _frame_num;													///< Frame number from the last IDR frame.

	/// Dependent members that are included based on NAL type, sequence param set and pic param set.
	int _field_pic_flag;										///< When present: 1 = slice is a field, 0 (default) = slice is a frame.
	int _bottom_field_flag;									///< When present: 1 = slice is part of bottom field, 0 (default) = top field.
	int _idr_pic_id;												///< For NAL unit = 5, increments for consecutive idr pictures, identifies which pic an I-slice belongs to.
	int _pic_order_cnt_lsb;									///< Modulo pic order count for top field of frame or for a coded field.
	int _delta_pic_order_cnt_bottom;				///< Pic order count difference between bottom and top field of a frame.
	int _delta_pic_order_cnt[2];						///< Pic order count difference from expected order count of the top/bottom field (default = 0);
	int _redundant_pic_cnt;									///< 0 = slice belongs to primary coded pic, greater than 0 = redundant coded pic number.

	int _direct_spatial_mv_pred_flag;				///< For B-slices, method used for decoding motion vectors.
	int _num_ref_idx_active_override_flag;	///< Activates/deactivates following members.
	int _num_ref_idx_l0_active_minus1;
	int _num_ref_idx_l1_active_minus1;

	/// Ref picture list re-ordering members.
	int _ref_pic_list_reordering_flag_l0;		///< Signals the reordering of the pictures in list 0.
	int _ref_pic_list_reordering_flag_l1;		///< Signals the reordering of the pictures in list 1 for B-frames.
	int _reordering_of_pic_nums_idc;
	int _abs_diff_pic_num_minus1;
	int _long_term_pic_num;

	/// Weighted prediction table members.
	// TODO: Add wieght pred table members.

	/// Decoded ref picture marking members.
	int _no_output_of_prior_pics_flag;
	int _long_term_reference_flag;					///< Mark this IDR picture slice for long term reference.
	int _adaptive_ref_pic_marking_mode_flag;	
	// TODO: Add dec ref pic marking members for memory management control.

	int _cabac_init_idc;									///< Index for initialisation table for arethmetic entropy coding.

	int _qp;															///< QP used in this slice. (Not in stream.)
	int _qp_delta;												///< Change in QP from the previous slice.

	int _sp_for_switch_flag;							///< Specifies decoding process for SP-Slices.
	int _qs_delta;												///< Change in QS from previous slice.

	/// 0 = All edges are filtered, 1 = Filtering is disabled, 2 = Filter enabled but not on slice boundaries.
	int _disable_deblocking_filter_idc;		///< Control of the deblocking process is defined by this flag. (0 = default.)
	int _alpha_c0_offset_div2;						///< Offset in alpha and tC0 filter tables.
	int _beta_offset_div2;								///< Offset in beta filter table.

	int _group_change_cycle;							///< Slice group map unit change.

};// end class SliceHeaderH264.

#endif	//_SLICEHEADERH264_H
========== END FILE: CodecUtils/SliceHeaderH264.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x2H264VlcDecoder.cpp ==========
Bundle entry: 125
Original bytes: 5149
Original SHA-256: 655ad667ad0fa9bb995f834ded03341e52864fc62d8fbfde837dcc49f59bfb28
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x2H264VlcDecoder

TAG						: TZ2H264VD

FILE NAME			: TotalZeros2x2H264VlcDecoder.cpp

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(a) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros2x2H264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros2x2H264VlcDecoder::TotalZeros2x2H264VlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

TotalZeros2x2H264VlcDecoder::~TotalZeros2x2H264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode total coeff - trailing ones - neighbour total coeffs symbols from the bit stream.
The first 2 param symbols represent total zeros and total coeffs. The total coeffs is an 
input that selects the appropriate vlc array for the total zero decoding. For fast implementation 
the tree splitting is done in the code.
@param bsr			: Bit stream to get from.
@param symbol1	: Returned total zeros for this block
@param symbol2	: Total num of coeffs in this block
@return					: Num of bits extracted.
*/
int	TotalZeros2x2H264VlcDecoder::Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
{
	int totalCoeffs	= *symbol2;	///< Used as an input.

	/// Reset bits extracted.
  _numCodeBits	= 0;
	int tZ				= 0;

	/// Select the method depending on the total number of coeffs.
	switch(totalCoeffs)
	{
		case 1:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; tZ = 0;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 1;
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; tZ = 2;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; tZ = 3;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 1...
			break;
		case 2:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; tZ = 0;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 1;
					}//end if 01...
					else						///< 00
					{
						_numCodeBits = 2; tZ = 2;
					}//end else 00...
				}//end else 0...
			}//end case 2...
			break;
		case 3:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; tZ = 0;
				}//end if 1...
				else						///< 0
				{
					_numCodeBits = 1; tZ = 1;
				}//end else 0...
			}//end case 3...
			break;
		default:	///< Invalid input.
			_numCodeBits = 0;	tZ = 0;
			break;
	}//end switch totalCoeffs...

	/// Load 'em up.
	*symbol1 = tZ;

  return(_numCodeBits);
}//end Decode2.


========== END FILE: CodecUtils/TotalZeros2x2H264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x2H264VlcDecoder.h ==========
Bundle entry: 126
Original bytes: 3388
Original SHA-256: d1d550282ed21e4d8b0afd441867fb48044c4c966cca18574c2c57a101848b55
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x2H264VlcDecoder

TAG						: TZ2H264VD

FILE NAME			: TotalZeros2x2H264VlcDecoder.h

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(a) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS2X2H264VLCDECODER_H
#define _TOTALZEROS2X2H264VLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros2x2H264VlcDecoder : public IVlcDecoder
{
public:
	TotalZeros2x2H264VlcDecoder();
	virtual ~TotalZeros2x2H264VlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Decode(IBitStreamReader* bsr) { _numCodeBits = 0; return(0); } 

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros (output) and total coeffs (input), respectively.
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2);

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class TotalZeros2x2H264VlcDecoder.

#endif	// _TOTALZEROS2X2H264VLCDECODER_H
========== END FILE: CodecUtils/TotalZeros2x2H264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x2H264VlcEncoder.cpp ==========
Bundle entry: 127
Original bytes: 4224
Original SHA-256: 7e777d56b971e62f49f21560174a888cb3df3e4ed2ad05399f8f12799e64684d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x2H264VlcEncoder

TAG						: TZ2H264VE

FILE NAME			: TotalZeros2x2H264VlcEncoder.cpp

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(a) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros2x2H264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros2x2H264VlcEncoder::TotalZeros2x2H264VlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
}//end constructor.

TotalZeros2x2H264VlcEncoder::~TotalZeros2x2H264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode total zeros - total coeffs symbols.
The 2 param symbols represent total zeros and total coeffs, respectively, and 
are encoded with the number of bits returned. The _numCodeBits and _bitCode 
members are set accordingly.
@param symbol1	:	Total zeros in this block 
@param symbol2	: Total coeffs for this block
@return					: Num of bits in the codeword.
*/
int	TotalZeros2x2H264VlcEncoder::Encode2(int symbol1, int symbol2)
{
	int totalZeros	= symbol1;
	int totalCoeffs	= symbol2;

	_bitCode			= table[totalZeros][totalCoeffs].codeWord;
	_numCodeBits	= table[totalZeros][totalCoeffs].numBits;

	return(_numCodeBits);
}// end Encode2.


/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const TZ2H264VE_VlcCodeType TotalZeros2x2H264VlcEncoder::table[4][4] = 
{///<	0				 1				2				 3	= totalCoeffs.
	{ { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, ///< 0 = totalZeros.
	{ { 0, 0}, { 2, 1}, { 2, 1}, { 1, 0} }, ///< 1
	{ { 0, 0}, { 3, 1}, { 2, 0}, { 0, 0} }, ///< 2
	{ { 0, 0}, { 3, 0}, { 0, 0}, { 0, 0} } 	///< 3
};


========== END FILE: CodecUtils/TotalZeros2x2H264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x2H264VlcEncoder.h ==========
Bundle entry: 128
Original bytes: 3778
Original SHA-256: fb5527ffcc191ba7b635a49d9508396a0c69fd86a593d67206aa26faea1652dd
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x2H264VlcEncoder

TAG						: TZ2H264VE

FILE NAME			: TotalZeros2x2H264VlcEncoder.h

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(a) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS2X2H264VLCENCODER_H
#define _TOTALZEROS2X2H264VLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Type definitions.
---------------------------------------------------------------------------
*/
typedef struct _TZ2H264VE_VlcCodeType
{
  int		numBits;	///< Num of bits in code word.
  int		codeWord;	///< Code word bit representation.
} TZ2H264VE_VlcCodeType;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros2x2H264VlcEncoder : public IVlcEncoder
{
public:
	TotalZeros2x2H264VlcEncoder(void);
	virtual ~TotalZeros2x2H264VlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros and total coeffs, respectively.
	virtual int	Encode2(int symbol1, int symbol2);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

	/// Constants of table sets.
	static const TZ2H264VE_VlcCodeType table[4][4];

};// end class TotalZeros2x2H264VlcEncoder.

#endif	// end _TOTALZEROS2X2H264VLCENCODER_H.
========== END FILE: CodecUtils/TotalZeros2x2H264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x4H264VlcDecoder.cpp ==========
Bundle entry: 129
Original bytes: 8256
Original SHA-256: 046ee4fc58dcfcaafa209884e96e9b180c135ac2cc1eea94232ac9755de847c1
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x4H264VlcDecoder

TAG						: TZ2X4H264VD

FILE NAME			: TotalZeros2x4H264VlcDecoder.cpp

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(b) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros2x4H264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros2x4H264VlcDecoder::TotalZeros2x4H264VlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

TotalZeros2x4H264VlcDecoder::~TotalZeros2x4H264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode total zeros and total coeffs symbols from the bit stream.
The first 2 param symbols represent total zeros and total coeffs. The total coeffs 
is an input that selects the appropriate vlc array for the total zero decoding. 
For fast implementation the tree splitting is done in the code.
@param bsr			: Bit stream to get from.
@param symbol1	: Returned total zeros for this block
@param symbol2	: Total num of coeffs in this block (input)
@return					: Num of bits extracted.
*/
int	TotalZeros2x4H264VlcDecoder::Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
{
	int totalCoeffs	= *symbol2;	///< Used as an input.

	/// Reset bits extracted.
  _numCodeBits	= 0;
	int tZ				= 0;

	/// Select the method depending on the total number of coeffs.
	switch(totalCoeffs)
	{
		case 1:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; tZ = 0;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						if(bsr->Read())	///< 011
						{
							_numCodeBits = 3; tZ = 2;
						}//end if 011...
						else						///< 010
						{
							_numCodeBits = 3; tZ = 1;
						}//end else 010...
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							if(bsr->Read())	///< 0011
							{
								_numCodeBits = 4; tZ = 4;
							}//end if 0011...
							else						///< 0010
							{
								_numCodeBits = 4; tZ = 3;
							}//end else 0010...
						}//end if 001...
						else						///< 000
						{
							if(bsr->Read())	///< 0001
							{
								_numCodeBits = 4; tZ = 5;
							}//end if 0001...
							else						///< 0000
							{
								if(bsr->Read())	///< 0000 1
								{
									_numCodeBits = 5; tZ = 6;
								}//end if 0000 1...
								else						///< 0000 0
								{
									_numCodeBits = 5; tZ = 7;
								}//end else 0000 0...
							}//end else 0000...
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 1...
			break;
		case 2:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						if(bsr->Read())	///< 111
						{
							_numCodeBits = 3; tZ = 6;
						}//end if 111...
						else						///< 110
						{
							_numCodeBits = 3; tZ = 5;
						}//end else 110...
					}//end if 11...
					else						///< 10
					{
						if(bsr->Read())	///< 101
						{
							_numCodeBits = 3; tZ = 4;
						}//end if 101...
						else						///< 100
						{
							_numCodeBits = 3; tZ = 3;
						}//end else 100...
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 1;
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; tZ = 2;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; tZ = 0;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 2...
			break;
		case 3:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						if(bsr->Read())	///< 111
						{
							_numCodeBits = 3; tZ = 5;
						}//end if 111...
						else						///< 110
						{
							_numCodeBits = 3; tZ = 4;
						}//end else 110...
					}//end if 11...
					else						///< 10
					{
						_numCodeBits = 2; tZ = 3;
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 2;
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; tZ = 1;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 3; tZ = 0;
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 3...
			break;
		case 4:
			{
				if(bsr->Read())	///< 1
				{
					if(bsr->Read())	///< 11
					{
						if(bsr->Read())	///< 111
						{
							_numCodeBits = 3; tZ = 4;
						}//end if 111...
						else						///< 110
						{
							_numCodeBits = 3; tZ = 0;
						}//end else 110...
					}//end if 11...
					else						///< 10
					{
						_numCodeBits = 2; tZ = 3;
					}//end else 10...
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 2;
					}//end if 01...
					else						///< 00
					{
						_numCodeBits = 2; tZ = 1;
					}//end else 00...
				}//end else 0...
			}//end case 4...
			break;
		case 5:
			_numCodeBits = 2; tZ = bsr->Read(2);
			break;
		case 6:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; tZ = 2;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; tZ = 1;
					}//end if 01...
					else						///< 00
					{
						_numCodeBits = 2; tZ = 0;
					}//end else 00...
				}//end else 0...
			}//end case 6...
			break;
		case 7:
			_numCodeBits = 1; tZ = bsr->Read();
			break;
		default:	///< Invalid input.
			_numCodeBits = 0;	tZ = 0;
			break;
	}//end switch totalCoeffs...

	/// Load 'em up.
	*symbol1 = tZ;

  return(_numCodeBits);
}//end Decode2.


========== END FILE: CodecUtils/TotalZeros2x4H264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x4H264VlcDecoder.h ==========
Bundle entry: 130
Original bytes: 3390
Original SHA-256: 2998f53f24c4de7fae602785eb370619cd45b22462067dfb91b87b6fd5627aa3
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x4H264VlcDecoder

TAG						: TZ2X4H264VD

FILE NAME			: TotalZeros2x4H264VlcDecoder.h

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(b) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS2X4H264VLCDECODER_H
#define _TOTALZEROS2X4H264VLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros2x4H264VlcDecoder : public IVlcDecoder
{
public:
	TotalZeros2x4H264VlcDecoder();
	virtual ~TotalZeros2x4H264VlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Decode(IBitStreamReader* bsr) { _numCodeBits = 0; return(0); } 

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros (output) and total coeffs (input), respectively.
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2);

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class TotalZeros2x4H264VlcDecoder.

#endif	// _TOTALZEROS2X4H264VLCDECODER_H
========== END FILE: CodecUtils/TotalZeros2x4H264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x4H264VlcEncoder.cpp ==========
Bundle entry: 131
Original bytes: 4733
Original SHA-256: a8e4747ae58d4da0c5128e76c9fe0c79efecda4d6c480379186d97497ba26dcc
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x4H264VlcEncoder

TAG						: TZ2X4H264VE

FILE NAME			: TotalZeros2x4H264VlcEncoder.cpp

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(b) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros2x4H264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros2x4H264VlcEncoder::TotalZeros2x4H264VlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
}//end constructor.

TotalZeros2x4H264VlcEncoder::~TotalZeros2x4H264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode total zeros - total coeffs symbols.
The 2 param symbols represent total zeros and total coeffs, respectively, and 
are encoded with the number of bits returned. The _numCodeBits and _bitCode 
members are set accordingly.
@param symbol1	:	Total zeros in this block 
@param symbol2	: Total coeffs for this block
@return					: Num of bits in the codeword.
*/
int	TotalZeros2x4H264VlcEncoder::Encode2(int symbol1, int symbol2)
{
	int totalZeros	= symbol1;
	int totalCoeffs	= symbol2;

	_bitCode			= table[totalZeros][totalCoeffs].codeWord;
	_numCodeBits	= table[totalZeros][totalCoeffs].numBits;

	return(_numCodeBits);
}// end Encode2.


/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const TZ2X4H264VE_VlcCodeType TotalZeros2x4H264VlcEncoder::table[8][8] = 
{///<	0				 1				2				 3				4				 5				6				 7	= totalCoeffs.
	{ { 0, 0}, { 1, 1}, { 3, 0}, { 3, 0}, { 3, 6}, { 2, 0}, { 2, 0}, { 1, 0} },	///< 0 = totalZeros.
	{ { 0, 0}, { 3, 2}, { 2, 1}, { 3, 1}, { 2, 0}, { 2, 1}, { 2, 1}, { 1, 1} },	///< 1
	{ { 0, 0}, { 3, 3}, { 3, 1}, { 2, 1}, { 2, 1}, { 2, 2}, { 1, 1}, { 0, 0} },	///< 2
	{ { 0, 0}, { 4, 2}, { 3, 4}, { 2, 2}, { 2, 2}, { 2, 3}, { 0, 0}, { 0, 0} },	///< 3
	{ { 0, 0}, { 4, 3}, { 3, 5}, { 3, 6}, { 3, 7}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 4
	{ { 0, 0}, { 4, 1}, { 3, 6}, { 3, 7}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 5
	{ { 0, 0}, { 5, 1}, { 3, 7}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 6
	{ { 0, 0}, { 5, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }	///< 7
};


========== END FILE: CodecUtils/TotalZeros2x4H264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros2x4H264VlcEncoder.h ==========
Bundle entry: 132
Original bytes: 3786
Original SHA-256: 9cac71414be0805375b07fd525ee15220ec48b569ca9674aaeb2a2db84309330
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros2x4H264VlcEncoder

TAG						: TZ2X4H264VE

FILE NAME			: TotalZeros2x4H264VlcEncoder.h

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.9(b) page 205. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS2X4H264VLCENCODER_H
#define _TOTALZEROS2X4H264VLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Type definitions.
---------------------------------------------------------------------------
*/
typedef struct _TZ2X4H264VE_VlcCodeType
{
  int		numBits;	///< Num of bits in code word.
  int		codeWord;	///< Code word bit representation.
} TZ2X4H264VE_VlcCodeType;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros2x4H264VlcEncoder : public IVlcEncoder
{
public:
	TotalZeros2x4H264VlcEncoder(void);
	virtual ~TotalZeros2x4H264VlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros and total coeffs, respectively.
	virtual int	Encode2(int symbol1, int symbol2);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

	/// Constants of table sets.
	static const TZ2X4H264VE_VlcCodeType table[8][8];

};// end class TotalZeros2x4H264VlcEncoder.

#endif	// end _TOTALZEROS2X4H264VLCENCODER_H.
========== END FILE: CodecUtils/TotalZeros2x4H264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros4x4H264VlcDecoder.cpp ==========
Bundle entry: 133
Original bytes: 23743
Original SHA-256: beaf1f642955eb065fb2bf8418049d3e9bb51906f45ecaf8e60f8c6c44c6588f
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros4x4H264VlcDecoder

TAG						: TZ4H264VD

FILE NAME			: TotalZeros4x4H264VlcDecoder.cpp

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.7 page 204. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros4x4H264VlcDecoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros4x4H264VlcDecoder::TotalZeros4x4H264VlcDecoder(void)
{
	_numCodeBits	= 0;
}//end constructor.

TotalZeros4x4H264VlcDecoder::~TotalZeros4x4H264VlcDecoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Decode total coeff - trailing ones - neighbour total coeffs symbols from the bit stream.
The first 2 param symbols represent total zeros and total coeffs. The total coeffs is an 
input that selects the appropriate vlc array for the total zero decoding. For fast implementation 
the tree splitting is done in the code.
@param bsr			: Bit stream to get from.
@param symbol1	: Returned total zeros for this block
@param symbol2	: Total num of coeffs in this block
@return					: Num of bits extracted.
*/
int	TotalZeros4x4H264VlcDecoder::Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2)
{
	int totalCoeffs	= *symbol2;	///< Used as an input.

	/// Reset bits extracted.
  _numCodeBits = 0;

	/// Select the method depending on the total number of coeffs.
	switch(totalCoeffs)
	{
		case 1:
			_numCodeBits	= TC1(bsr, symbol1);
			break;
		case 2:
			_numCodeBits	= TC2(bsr, symbol1);
			break;
		case 3:
			_numCodeBits	= TC3(bsr, symbol1);
			break;
		case 4:
			_numCodeBits	= TC4(bsr, symbol1);
			break;
		case 5:
			_numCodeBits	= TC5(bsr, symbol1);
			break;
		case 6:
			_numCodeBits	= TC6(bsr, symbol1);
			break;
		case 7:
			_numCodeBits	= TC7(bsr, symbol1);
			break;
		case 8:
			_numCodeBits	= TC8(bsr, symbol1);
			break;
		case 9:
			_numCodeBits	= TC9(bsr, symbol1);
			break;
		case 10:
			_numCodeBits	= TC10(bsr, symbol1);
			break;
		case 11:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; *symbol1 = 4;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						if(bsr->Read())	///< 011
						{
							_numCodeBits = 3; *symbol1 = 5;
						}//end if 011...
						else						///< 010
						{
							_numCodeBits = 3; *symbol1 = 3;
						}//end else 010...
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; *symbol1 = 2;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 4; *symbol1 = bsr->Read();
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 11...
			break;
		case 12:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; *symbol1 = 3;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; *symbol1 = 2;
					}//end if 01...
					else						///< 00
					{
						if(bsr->Read())	///< 001
						{
							_numCodeBits = 3; *symbol1 = 4;
						}//end if 001...
						else						///< 000
						{
							_numCodeBits = 4; *symbol1 = bsr->Read();
						}//end else 000...
					}//end else 00...
				}//end else 0...
			}//end case 12...
			break;
		case 13:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; *symbol1 = 2;
				}//end if 1...
				else						///< 0
				{
					if(bsr->Read())	///< 01
					{
						_numCodeBits = 2; *symbol1 = 3;
					}//end if 01...
					else						///< 00
					{
						_numCodeBits = 3; *symbol1 = bsr->Read();
					}//end else 00...
				}//end else 0...
			}//end case 13...
			break;
		case 14:
			{
				if(bsr->Read())	///< 1
				{
					_numCodeBits = 1; *symbol1 = 2;
				}//end if 1...
				else						///< 0
				{
					_numCodeBits = 2; *symbol1 = bsr->Read();
				}//end else 0...
			}//end case 14...
			break;
		case 15:
			{
				_numCodeBits = 1; *symbol1	= bsr->Read();
			}//end case 15...
			break;
		default:	///< Invalid input.
			_numCodeBits = 0;	*symbol1 = 0;
			break;
	}//end switch totalCoeffs...

  return(_numCodeBits);
}//end Decode2.

/*
---------------------------------------------------------------------------
	Private Methods.
---------------------------------------------------------------------------
*/
/** Decode total zeros symbols from the bit stream.
For total coeffs from 1 to 10.
@param bsr				: Bit stream to get from.
@param totalZeros	: Returned total zeros for this block
@return						: Num of bits extracted.
*/
int	TotalZeros4x4H264VlcDecoder::TC1(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;

	if(bsr->Read())	///< 1
	{
		numBits = 1; tZs = 0;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 1;
			}//end if 011...
			else						///< 010
			{
				numBits = 3; tZs = 2;
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					numBits = 4; tZs = 3;
				}//end if 0011...
				else						///< 0010
				{
					numBits = 4; tZs = 4;
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						numBits = 5; tZs = 5;
					}//end if 0001 1...
					else						///< 0001 0
					{
						numBits = 5; tZs = 6;
					}//end else 0001 0 ...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						if(bsr->Read())	///< 0000 11
						{
							numBits = 6; tZs = 7;
						}//end if 0000 11...
						else						///< 0000 10
						{
							numBits = 6; tZs = 8;
						}//end else 0000 10 ...
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							if(bsr->Read())	///< 0000 011
							{
								numBits = 7; tZs = 9;
							}//end if 0000 011...
							else						///< 0000 010
							{
								numBits = 7; tZs = 10;
							}//end else 0000 010 ...
						}//end if 0000 01...
						else						///< 0000 00
						{
							if(bsr->Read())	///< 0000 001
							{
								if(bsr->Read())	///< 0000 0011
								{
									numBits = 8; tZs = 11;
								}//end if 0000 0011...
								else						///< 0000 0010
								{
									numBits = 8; tZs = 12;
								}//end else 0000 0010 ...
							}//end if 0000 001...
							else						///< 0000 000
							{
								if(bsr->Read())	///< 0000 0001
								{
									if(bsr->Read())	///< 0000 0001 1
									{
										numBits = 9; tZs = 13;
									}//end if 0000 0001 1...
									else						///< 0000 0001 0
									{
										numBits = 9; tZs = 14;
									}//end else 0000 0001 0 ...
								}//end if 0000 0001...
								else						///< 0000 0000
								{
									if(bsr->Read())	///< 0000 0000 1
									{
										numBits = 9; tZs = 15;
									}//end if 0000 0000 1...
								}//end else 0000 0000 ...
							}//end else 0000 000 ...
						}//end else 0000 00 ...
					}//end else 0000 0 ...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC1.

int	TotalZeros4x4H264VlcDecoder::TC2(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(2);
		switch(bits)
		{
			case 0:		///< 100
				tZs = 3;
				break;
			case 1:		///< 101
				tZs = 2;
				break;
			case 2:		///< 110
				tZs = 1;
				break;
			case 3:		///< 111
				tZs = 0;
				break;
		}//end switch bits...
		numBits = 3;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 4;
			}//end if 011...
			else						///< 010
			{
				if(bsr->Read())	///< 0101
				{
					numBits = 4; tZs = 5;
				}//end if 0101...
				else						///< 0100
				{
					numBits = 4; tZs = 6;
				}//end else 0100...
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					numBits = 4; tZs = 7;
				}//end if 0011...
				else						///< 0010
				{
					numBits = 4; tZs = 8;
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						numBits = 5; tZs = 9;
					}//end if 0001 1...
					else						///< 0001 0
					{
						numBits = 5; tZs = 10;
					}//end else 0001 0...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						if(bsr->Read())	///< 0000 11
						{
							numBits = 6; tZs = 11;
						}//end if 0000 11...
						else						///< 0000 10
						{
							numBits = 6; tZs = 12;
						}//end else 0000 10...
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 13;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 14;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC2.

int	TotalZeros4x4H264VlcDecoder::TC3(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(2);
		switch(bits)
		{
			case 0:		///< 100
				tZs = 6;
				break;
			case 1:		///< 101
				tZs = 3;
				break;
			case 2:		///< 110
				tZs = 2;
				break;
			case 3:		///< 111
				tZs = 1;
				break;
		}//end switch bits...
		numBits = 3;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 7;
			}//end if 011...
			else						///< 010
			{
				if(bsr->Read())	///< 0101
				{
					numBits = 4; tZs = 0;
				}//end if 0101...
				else						///< 0100
				{
					numBits = 4; tZs = 4;
				}//end else 0100...
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					numBits = 4; tZs = 5;
				}//end if 0011...
				else						///< 0010
				{
					numBits = 4; tZs = 8;
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						numBits = 5; tZs = 9;
					}//end if 0001 1...
					else						///< 0001 0
					{
						numBits = 5; tZs = 10;
					}//end else 0001 0...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 12;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 11;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 13;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC3.

int	TotalZeros4x4H264VlcDecoder::TC4(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(2);
		switch(bits)
		{
			case 0:		///< 100
				tZs = 6;
				break;
			case 1:		///< 101
				tZs = 5;
				break;
			case 2:		///< 110
				tZs = 4;
				break;
			case 3:		///< 111
				tZs = 1;
				break;
		}//end switch bits...
		numBits = 3;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 8;
			}//end if 011...
			else						///< 010
			{
				if(bsr->Read())	///< 0101
				{
					numBits = 4; tZs = 2;
				}//end if 0101...
				else						///< 0100
				{
					numBits = 4; tZs = 3;
				}//end else 0100...
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					numBits = 4; tZs = 7;
				}//end if 0011...
				else						///< 0010
				{
					numBits = 4; tZs = 9;
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					if(bsr->Read())	///< 0001 1
					{
						numBits = 5; tZs = 0;
					}//end if 0001 1...
					else						///< 0001 0
					{
						numBits = 5; tZs = 10;
					}//end else 0001 0...
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 11;
					}//end if 0000 1...
					else						///< 0000 0
					{
						numBits = 5; tZs = 12;
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC4.

int	TotalZeros4x4H264VlcDecoder::TC5(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(2);
		switch(bits)
		{
			case 0:		///< 100
				tZs = 6;
				break;
			case 1:		///< 101
				tZs = 5;
				break;
			case 2:		///< 110
				tZs = 4;
				break;
			case 3:		///< 111
				tZs = 3;
				break;
		}//end switch bits...
		numBits = 3;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 7;
			}//end if 011...
			else						///< 010
			{
				if(bsr->Read())	///< 0101
				{
					numBits = 4; tZs = 0;
				}//end if 0101...
				else						///< 0100
				{
					numBits = 4; tZs = 1;
				}//end else 0100...
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				if(bsr->Read())	///< 0011
				{
					numBits = 4; tZs = 2;
				}//end if 0011...
				else						///< 0010
				{
					numBits = 4; tZs = 8;
				}//end else 0010...
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 10;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 9;
					}//end if 0000 1...
					else						///< 0000 0
					{
						numBits = 5; tZs = 11;
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC5.

int	TotalZeros4x4H264VlcDecoder::TC6(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;
	int bits;

	if(bsr->Read())	///< 1
	{
		bits = bsr->Read(2);
		switch(bits)
		{
			case 0:		///< 100
				tZs = 5;
				break;
			case 1:		///< 101
				tZs = 4;
				break;
			case 2:		///< 110
				tZs = 3;
				break;
			case 3:		///< 111
				tZs = 2;
				break;
		}//end switch bits...
		numBits = 3;
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 6;
			}//end if 011...
			else						///< 010
			{
				numBits = 3; tZs = 7;
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tZs = 9;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 8;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs =1 ;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 0;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 10;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC6.

int	TotalZeros4x4H264VlcDecoder::TC7(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;

	if(bsr->Read())	///< 1
	{
		if(bsr->Read())	///< 11
		{
			numBits = 2; tZs = 5;
		}//end if 11...
		else						///< 10
		{
			if(bsr->Read())	///< 101
			{
				numBits = 3; tZs = 2;
			}//end if 101...
			else						///< 100
			{
				numBits = 3; tZs = 3;
			}//end else 100...
		}//end else 10...
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 4;
			}//end if 011...
			else						///< 010
			{
				numBits = 3; tZs = 6;
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tZs = 8;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 7;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 1;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 0;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 9;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC7.

int	TotalZeros4x4H264VlcDecoder::TC8(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;

	if(bsr->Read())	///< 1
	{
		if(bsr->Read())	///< 11
		{
			numBits = 2; tZs = 4;
		}//end if 11...
		else						///< 10
		{
			numBits = 2; tZs = 5;
		}//end else 10...
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			if(bsr->Read())	///< 011
			{
				numBits = 3; tZs = 3;
			}//end if 011...
			else						///< 010
			{
				numBits = 3; tZs = 6;
			}//end else 010...
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tZs = 7;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 1;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 2;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 0;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 8;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC8.

int	TotalZeros4x4H264VlcDecoder::TC9(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;

	if(bsr->Read())	///< 1
	{
		if(bsr->Read())	///< 11
		{
			numBits = 2; tZs = 3;
		}//end if 11...
		else						///< 10
		{
			numBits = 2; tZs = 4;
		}//end else 10...
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			numBits = 2; tZs = 6;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tZs = 5;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 2;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 7;
					}//end if 0000 1...
					else						///< 0000 0
					{
						if(bsr->Read())	///< 0000 01
						{
							numBits = 6; tZs = 0;
						}//end if 0000 01...
						else						///< 0000 00
						{
							numBits = 6; tZs = 1;
						}//end else 0000 00...
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC9.

int	TotalZeros4x4H264VlcDecoder::TC10(IBitStreamReader* bsr, int* totalZeros)
{
	int numBits	= 0;
	int tZs			= 0;

	if(bsr->Read())	///< 1
	{
		if(bsr->Read())	///< 11
		{
			numBits = 2; tZs = 3;
		}//end if 11...
		else						///< 10
		{
			numBits = 2; tZs = 4;
		}//end else 10...
	}//end if 1...
	else						///< 0
	{
		if(bsr->Read())	///< 01
		{
			numBits = 2; tZs = 5;
		}//end if 01...
		else						///< 00
		{
			if(bsr->Read())	///< 001
			{
				numBits = 3; tZs = 2;
			}//end if 001...
			else						///< 000
			{
				if(bsr->Read())	///< 0001
				{
					numBits = 4; tZs = 6;
				}//end if 0001...
				else						///< 0000
				{
					if(bsr->Read())	///< 0000 1
					{
						numBits = 5; tZs = 0;
					}//end if 0000 1...
					else						///< 0000 0
					{
						numBits = 5; tZs = 1;
					}//end else 0000 0...
				}//end else 0000...
			}//end else 000...
		}//end else 00...
	}//end else 0...

	/// Load 'em up.
	*totalZeros	= tZs;

	return(numBits);
}//end TC10.

========== END FILE: CodecUtils/TotalZeros4x4H264VlcDecoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros4x4H264VlcDecoder.h ==========
Bundle entry: 134
Original bytes: 3933
Original SHA-256: ecd236e56c4d9a52ca9f370e6cc858eb76eebc9c5fdbf3ba87593e114e012e16
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros4x4H264VlcDecoder

TAG						: TZ4H264VD

FILE NAME			: TotalZeros4x4H264VlcDecoder.h

DESCRIPTION		: A total zeros Vlc decoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.7 page 204. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcDecoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS4X4H264VLCDECODER_H
#define _TOTALZEROS4X4H264VLCDECODER_H

#pragma once

#include "IVlcDecoder.h"

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros4x4H264VlcDecoder : public IVlcDecoder
{
public:
	TotalZeros4x4H264VlcDecoder();
	virtual ~TotalZeros4x4H264VlcDecoder();

public:
	/// Interface implementation.
	int GetNumDecodedBits(void)	{ return(_numCodeBits); }
	int Marker(void)						{ return(0); }	///< No markers for this decoder.
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Decode(IBitStreamReader* bsr) { _numCodeBits = 0; return(0); } 

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros (output) and total coeffs (input), respectively.
	virtual int	Decode2(IBitStreamReader* bsr, int* symbol1, int* symbol2);

protected:
	/// Private methods.
	int	TC1(IBitStreamReader* bsr, int* totalZeros);
	int	TC2(IBitStreamReader* bsr, int* totalZeros);
	int	TC3(IBitStreamReader* bsr, int* totalZeros);
	int	TC4(IBitStreamReader* bsr, int* totalZeros);
	int	TC5(IBitStreamReader* bsr, int* totalZeros);
	int	TC6(IBitStreamReader* bsr, int* totalZeros);
	int	TC7(IBitStreamReader* bsr, int* totalZeros);
	int	TC8(IBitStreamReader* bsr, int* totalZeros);
	int	TC9(IBitStreamReader* bsr, int* totalZeros);
	int	TC10(IBitStreamReader* bsr, int* totalZeros);

protected:
	int _numCodeBits;	///< Number of coded bits for this symbol.

};// end class TotalZeros4x4H264VlcDecoder.

#endif	// _TOTALZEROS4X4H264VLCDECODER_H
========== END FILE: CodecUtils/TotalZeros4x4H264VlcDecoder.h ==========

========== BEGIN FILE: CodecUtils/TotalZeros4x4H264VlcEncoder.cpp ==========
Bundle entry: 135
Original bytes: 6613
Original SHA-256: 8569765d280ed6cb27dca4af80202e12b8d55f44c364b6f8f3acd7cdd0033b97
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros4x4H264VlcEncoder

TAG						: TZ4H264VE

FILE NAME			: TotalZeros4x4H264VlcEncoder.cpp

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.7 page 204. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include "TotalZeros4x4H264VlcEncoder.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
TotalZeros4x4H264VlcEncoder::TotalZeros4x4H264VlcEncoder(void)
{
	_numCodeBits	= 0;
	_bitCode			= 0;
}//end constructor.

TotalZeros4x4H264VlcEncoder::~TotalZeros4x4H264VlcEncoder(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Interface Methods.
---------------------------------------------------------------------------
*/
/** Encode total zeros - total coeffs symbols.
The 2 param symbols represent total zeros and total coeffs, respectively, and 
are encoded with the number of bits returned. The _numCodeBits and _bitCode 
members are set accordingly.
@param symbol1	:	Total zeros in this block 
@param symbol2	: Total coeffs for this block
@return					: Num of bits in the codeword.
*/
int	TotalZeros4x4H264VlcEncoder::Encode2(int symbol1, int symbol2)
{
	int totalZeros	= symbol1;
	int totalCoeffs	= symbol2;

	_bitCode			= table[totalZeros][totalCoeffs].codeWord;
	_numCodeBits	= table[totalZeros][totalCoeffs].numBits;

	return(_numCodeBits);
}// end Encode2.


/*
---------------------------------------------------------------------------
	Table Constants.
---------------------------------------------------------------------------
*/
const TZ4H264VE_VlcCodeType TotalZeros4x4H264VlcEncoder::table[16][16] = 
{///<	0				 1				2				 3				4				 5				6				 7				8				 9			 10				11			 12				13			 14				15	= totalCoeffs.
	{ { 0, 0}, { 1, 1}, { 3, 7}, { 4, 5}, { 5, 3}, { 4, 5}, { 6, 1}, { 6, 1}, { 6, 1}, { 6, 1}, { 5, 1}, { 4, 0}, { 4, 0}, { 3, 0}, { 2, 0}, { 1, 0} },	///< 0 = totalZeros.
	{ { 0, 0}, { 3, 3}, { 3, 6}, { 3, 7}, { 3, 7}, { 4, 4}, { 5, 1}, { 5, 1}, { 4, 1}, { 6, 0}, { 5, 0}, { 4, 1}, { 4, 1}, { 3, 1}, { 2, 1}, { 1, 1} },	///< 1
	{ { 0, 0}, { 3, 2}, { 3, 5}, { 3, 6}, { 4, 5}, { 4, 3}, { 3, 7}, { 3, 5}, { 5, 1}, { 4, 1}, { 3, 1}, { 3, 1}, { 2, 1}, { 1, 1}, { 1, 1}, { 0, 0} },	///< 2
	{ { 0, 0}, { 4, 3}, { 3, 4}, { 3, 5}, { 4, 4}, { 3, 7}, { 3, 6}, { 3, 4}, { 3, 3}, { 2, 3}, { 2, 3}, { 3, 2}, { 1, 1}, { 2, 1}, { 0, 0}, { 0, 0} },	///< 3
	{ { 0, 0}, { 4, 2}, { 3, 3}, { 4, 4}, { 3, 6}, { 3, 6}, { 3, 5}, { 3, 3}, { 2, 3}, { 2, 2}, { 2, 2}, { 1, 1}, { 3, 1}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 4
	{ { 0, 0}, { 5, 3}, { 4, 5}, { 4, 3}, { 3, 5}, { 3, 5}, { 3, 4}, { 2, 3}, { 2, 2}, { 3, 1}, { 2, 1}, { 3, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 5
	{ { 0, 0}, { 5, 2}, { 4, 4}, { 3, 4}, { 3, 4}, { 3, 4}, { 3, 3}, { 3, 2}, { 3, 2}, { 2, 1}, { 4, 1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 6
	{ { 0, 0}, { 6, 3}, { 4, 3}, { 3, 3}, { 4, 3}, { 3, 3}, { 3, 2}, { 4, 1}, { 3, 1}, { 5, 1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 7
	{ { 0, 0}, { 6, 2}, { 4, 2}, { 4, 2}, { 3, 3}, { 4, 2}, { 4, 1}, { 3, 1}, { 6, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 8
	{ { 0, 0}, { 7, 3}, { 5, 3}, { 5, 3}, { 4, 2}, { 5, 1}, { 3, 1}, { 6, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 9
	{ { 0, 0}, { 7, 2}, { 5, 2}, { 5, 2}, { 5, 2}, { 4, 1}, { 6, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 10
	{ { 0, 0}, { 8, 3}, { 6, 3}, { 6, 1}, { 5, 1}, { 5, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 11
	{ { 0, 0}, { 8, 2}, { 6, 2}, { 5, 1}, { 5, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 12
	{ { 0, 0}, { 9, 3}, { 6, 1}, { 6, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 13
	{ { 0, 0}, { 9, 2}, { 6, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} },	///< 14
	{ { 0, 0}, { 9, 1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }	///< 15
};


========== END FILE: CodecUtils/TotalZeros4x4H264VlcEncoder.cpp ==========

========== BEGIN FILE: CodecUtils/TotalZeros4x4H264VlcEncoder.h ==========
Bundle entry: 136
Original bytes: 3777
Original SHA-256: b40b089effdd1fdf525e55cab131ec2241fd0d29a40e820ba5e78ea824bfb374
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: TotalZeros4x4H264VlcEncoder

TAG						: TZ4H264VE

FILE NAME			: TotalZeros4x4H264VlcEncoder.h

DESCRIPTION		: A total zeros Vlc encoder implementation as defined in
								H.264 Recommendation (03/2005) Table 9.7 page 204. The 
								total number of coeffs defines which vlc array to use. 
								This implementation is implemented with an IVlcEncoder 
								Interface.

COPYRIGHT			: (c)CSIR 2007-2010 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _TOTALZEROS4X4H264VLCENCODER_H
#define _TOTALZEROS4X4H264VLCENCODER_H

#include "IVlcEncoder.h"

/*
---------------------------------------------------------------------------
	Type definitions.
---------------------------------------------------------------------------
*/
typedef struct _TZ4H264VE_VlcCodeType
{
  int		numBits;	///< Num of bits in code word.
  int		codeWord;	///< Code word bit representation.
} TZ4H264VE_VlcCodeType;

/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class TotalZeros4x4H264VlcEncoder : public IVlcEncoder
{
public:
	TotalZeros4x4H264VlcEncoder(void);
	virtual ~TotalZeros4x4H264VlcEncoder(void);

public:
	/// Interface implementation.
	int GetNumCodedBits(void)	{ return(_numCodeBits); }
	int GetCode(void)					{ return(_bitCode); }
	/// A single symbol has no meaning for combined multi symbol encoding.
	virtual int Encode(int symbol) { return(0); }

	/// Optional interface implementation.
	/// The 2 symbols represent total zeros and total coeffs, respectively.
	virtual int	Encode2(int symbol1, int symbol2);

protected:
	int 	_numCodeBits;	///< Number of coded bits for the encoding.
	int 	_bitCode;			///< The code of length numCodeBits.

	/// Constants of table sets.
	static const TZ4H264VE_VlcCodeType table[16][16];

};// end class TotalZeros4x4H264VlcEncoder.

#endif	// end _TOTALZEROS4X4H264VLCENCODER_H.
========== END FILE: CodecUtils/TotalZeros4x4H264VlcEncoder.h ==========

========== BEGIN FILE: CodecUtils/VectorStructList.cpp ==========
Bundle entry: 137
Original bytes: 8003
Original SHA-256: d34ada0515332c413bd633be9396ceb2ce1c45e3e53162739978e442a9fc78a8
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: VectorStructList

TAG						: VSL

FILE NAME			: VectorStructList.cpp

DESCRIPTION		: A generic base class to contain vectors in a contiguous 
								list of structs defined by the extended implementations.
								The structure of the vectors is determined by its type.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <memory.h>
#include <string.h>
#include <stdlib.h>

#include "VectorStructList.h"
#include "GeneralUtils/MeasurementTable.h"

/*
--------------------------------------------------------------------------
  Constants. 
--------------------------------------------------------------------------
*/
const int	VectorStructList::SIMPLE2D	= 0;
const int	VectorStructList::COMPLEX2D	= 1;

/*
--------------------------------------------------------------------------
  Construction and destruction. 
--------------------------------------------------------------------------
*/
/** Construction.
No mem is alloc in the constructor and is left for the SetLength()
member.
*/
VectorStructList::VectorStructList(int type, int dim, int maxVecsPerStruct)
{
	_type							= type;
	_dim							= dim;
	_maxVecsPerStruct	= maxVecsPerStruct;
	_length						= 0;
	_pData						= NULL;
}//end constructor.

VectorStructList::~VectorStructList(void)
{
	Delete();
}//end destructor.

void VectorStructList::Delete(void)
{
	if(_pData != NULL)
	{
		if(_type == COMPLEX2D)
		{
			VCL_COMPLEX_2D_TYPE* p = (VCL_COMPLEX_2D_TYPE *)_pData;
			for(int i = 0; i < _length; i++)
				delete[] p[i].vec;

                        delete[] p;
		}//end if _type.i..
                else
                {
                  VCL_2D_TYPE* pData = (VCL_2D_TYPE*)_pData;
		  delete[] pData;
                }
	}//end if _pData...
	_pData	= NULL;
	_length = 0;
}//end Delete.

/*
--------------------------------------------------------------------------
  Public member interface. 
--------------------------------------------------------------------------
*/
/** Set mem size dependent on type and length of vector list.
There is no checking on the validity of the members set during construction.
@param	length	: Num of structs in _pData;
@return					: 1 = success, 0 = failure.
*/
int VectorStructList::SetLength(int length)
{
	if(length < 0)
		return(0);

	// Clear out old mem.
	if(_pData != NULL)
		Delete();

	// Create new space on construction parameters.
	if(_type == SIMPLE2D)
	{
		_pData = new VCL_2D_TYPE[length];
		_maxVecsPerStruct = 1;	// Forced to 1 for simple.
	}//end if _type...
	else if(_type == COMPLEX2D)
		_pData = new VCL_COMPLEX_2D_TYPE[length];
	if(_pData == NULL)
		return(0);

	_length = length;
	_dim		= 2;		// Forced to 2D.

	// Complex type requires filling in.
	if(_type == COMPLEX2D)
	{
		VCL_COMPLEX_2D_TYPE* p = (VCL_COMPLEX_2D_TYPE *)_pData;
		for(int i = 0; i < _length; i++)
		{
			p[i].pattern		= 0;
			p[i].numVectors = 0;
			p[i].vec				= new VCL_2D_TYPE[_maxVecsPerStruct];
		}//end for i...
	}//end if _type...

	return(1);
}//end SetLength.

/** Get a ptr to the desired struct in the list.
@param pos	: Position in the list.
@return			: Generic ptr to struct at position pos.
*/
void* VectorStructList::GetStructPtr(int pos)
{
	if( (_pData == NULL)||(pos >= _length) )
		return(NULL);

	void* p = NULL;

	if(_type == SIMPLE2D)
	{
		VCL_2D_TYPE* ps = (VCL_2D_TYPE *)_pData;
		p = &(ps[pos]);
	}//end if _type...
	else if(_type == COMPLEX2D)
	{
		VCL_COMPLEX_2D_TYPE* pc = (VCL_COMPLEX_2D_TYPE *)_pData;
		p = &(pc[pos]);
	}//end else...

	return(p); 
}//end GetStructPtr.

/** Set the element in a simple vector list.
No bounds checking is done so be careful.
@param pos			: Struct position in the list.
@param element	: Element within the vector.
@param val			: Value to set.
*/
void VectorStructList::SetSimpleElement(int pos, int element, int val)
{
	VCL_2D_TYPE* p = (VCL_2D_TYPE *)_pData;
	if(element == 0)
		p[pos].x = (short)val;
	else if(element == 1)
		p[pos].y = (short)val;
}//end SetSimpleElement.

int	VectorStructList::GetSimpleElement(int pos, int element)
{
	VCL_2D_TYPE* p = (VCL_2D_TYPE *)_pData;
	int val = 0;
	if(element == 0)
		val = (int)(p[pos].x);
	else if(element == 1)
		val = (int)(p[pos].y);
	return(val);
}//end GetSimpleElement.

/** Set the element in a complex vector list.
No bounds checking is done so be careful.
@param pos			: Struct position in the list.
@param vec			: Vector in the pattern.
@param element	: Element within the vector.
@param val			: Value to set.
*/
void VectorStructList::SetComplexElement(int pos, int vec, int element, int val)
{
	VCL_COMPLEX_2D_TYPE* p = (VCL_COMPLEX_2D_TYPE *)_pData;
	if(element == 0)
		p[pos].vec[vec].x = (short)val;
	else if(element == 1)
		p[pos].vec[vec].y = (short)val;
}//end SetComplexElement.

int	VectorStructList::GetComplexElement(int pos, int vec, int element)
{
	VCL_COMPLEX_2D_TYPE* p = (VCL_COMPLEX_2D_TYPE *)_pData;
	int val = 0;
	if(element == 0)
		val = (int)(p[pos].vec[vec].x);
	else if(element == 1)
		val = (int)(p[pos].vec[vec].y);
	return(val);
}//end GetComplexElement.

/** Dump the list into a file.
Treat all elements as type integer.
@param filename : File name to use.
@param title    : Title to use in the text file.
@return         : None.
*/
void VectorStructList::Dump(char* filename, const char* title)
{
  int i; 

  /// Currently only support simple type.
	if(_type != SIMPLE2D)
    return;

  MeasurementTable* pT = new MeasurementTable();
	pT->SetTitle(title);

	pT->Create(2, _length);
  /// Motion X
  pT->SetHeading(0, "mv x");
  pT->SetDataType(0, MeasurementTable::INT);
  /// Motion Y
  pT->SetHeading(1, "mv y");
  pT->SetDataType(1, MeasurementTable::INT);

	for(i = 0; i < _length; i++)
  {
		pT->WriteItem(0, i, GetSimpleElement(i, 0));
		pT->WriteItem(1, i, GetSimpleElement(i, 1));
  }//end for i...

  pT->Save(filename, ",", 1);

  delete pT;
}//end Dump.

========== END FILE: CodecUtils/VectorStructList.cpp ==========

========== BEGIN FILE: CodecUtils/VectorStructList.h ==========
Bundle entry: 138
Original bytes: 4651
Original SHA-256: 332640c7b369389c7229842c094dac5df222800590146a034a482a874a918381
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: VectorStructList

TAG						: VSL

FILE NAME			: VectorStructList.h

DESCRIPTION		: A generic base class to contain vectors in a contiguous 
								list of structs defined by the extended implementations.
								The structure of the vectors is determined by its type.

COPYRIGHT			: (c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#ifndef _VECTORSTRUCTLIST_H
#define _VECTORSTRUCTLIST_H

/*
---------------------------------------------------------------------------
	Vector type description.
---------------------------------------------------------------------------
*/

// Two Structs are defined for general 2-D vectors and 2-D patterns. Each 
// implementation either uses these or defines its own.

// Simple structure. _type = SIMPLE:
typedef struct _VSL_2D_TYPE
{
	short x;
	short y;
} VCL_2D_TYPE;

// Complex structure.	_type = COMPLEX:
typedef struct _VSL_COMPLEX_2D_TYPE
{
	int						pattern;		// Describes the meaning of the pattern of vectors.
	int						numVectors;	// Valid vectors in vec.
	VCL_2D_TYPE*	vec;				// Array of length _maxVecsPerStruct.
} VCL_COMPLEX_2D_TYPE;

/*
---------------------------------------------------------------------------
	Class definitions.
---------------------------------------------------------------------------
*/
class VectorStructList
{
	public:
		VectorStructList(int type, int dim = 2, int maxVecsPerStruct = 1);
		virtual ~VectorStructList(void);

		// Set mem size dependent on type and length of list.
		virtual int	SetLength(int length);
		// Get the struct at a specific position in the list.
		virtual void* GetStructPtr(int pos);

		int		GetType(void)								{ return(_type); }
		int		GetDimension(void)					{ return(_dim); }
		int		GetMaxVecsPerStruct(void)		{ return(_maxVecsPerStruct); }
		int		GetLength(void)							{ return(_length); }
		void* GetListPtr(void)						{ return(_pData); }

		// Vector element access interface.
		virtual void	SetSimpleElement(int pos, int element, int val);
		virtual int		GetSimpleElement(int pos, int element);
		virtual void	SetComplexElement(int pos, int vec, int element, int val);
		virtual int		GetComplexElement(int pos, int vec, int element);
    virtual void  Dump(char* filename, const char* title);

	public:
		static const int	SIMPLE2D;
		static const int	COMPLEX2D;

	protected:
		virtual void Delete(void);

	protected:
		int		_type;							// SIMPLE/COMPLEX or implementation defined.
		int		_dim;								// Vector dimension.
		int		_maxVecsPerStruct;	// Max vectors per pattern. (Default = 1 for SIMPLE.)
		int		_length;						// Num of patterns of type _type.	( Is num of vecs for SIMPLE).

		// The data list is stored in an array whose structure 
		// is dependent on the type and length.
		void*	_pData;	
};//end VectorStructList.


#endif // _VECTORSTRUCTLIST_H

========== END FILE: CodecUtils/VectorStructList.h ==========

========== BEGIN FILE: CodecUtils/YuvRawFileHandler.cpp ==========
Bundle entry: 139
Original bytes: 5945
Original SHA-256: 15bfb7765f9210a8396d2cbd61818b0b4b39b530c11c044adb2eaeaf349cb9e5
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: YuvRawFileHandler

TAG						: YUVRFH

FILE NAME			: YuvRawFileHandler.cpp

DESCRIPTION		: A class to hold raw yuv data used for video codec testing.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <fstream>

#include "YuvRawFileHandler.h"

/*
---------------------------------------------------------------------------
	Construction and destruction.
---------------------------------------------------------------------------
*/
YuvRawFileHandler::YuvRawFileHandler(void): RawFileHandlerBase()
{
  _pBuff16  = NULL;
  _pBuff8   = NULL;
  _buffLen  = 0;
  _inType   = YUV4208P;
  _outType  = YUV42016P;
  _width    = 352;
  _height   = 288;
}//end constructor.

YuvRawFileHandler::~YuvRawFileHandler(void)
{
}//end destructor.

/*
---------------------------------------------------------------------------
	Public interface methods.
---------------------------------------------------------------------------
*/
int YuvRawFileHandler::Open(const char* filename, int rw)
{
   /// Clear previous stuff.
  Close();

 if(!RawFileHandlerBase::Open(filename, rw))
    return(0);

  /// Buffer for 1 frame of planar YUV. 
  _buffLen  = (_width * _height) + ((_width * _height)/2); ///< YUV 4:2:0
  if(_outType == YUV42016P)
  {
    _pBuff16 = new short[_buffLen];
    if(_pBuff16 == NULL)
    {
      Close();
      return(0);
    }//end if !_pBuff16...
  }//end if _outType...
  else
  {
    _pBuff8 = new unsigned char[_buffLen];
    if(_pBuff8 == NULL)
    {
      Close();
      return(0);
    }//end if !_pBuff8...
  }//end else...

  return(1);
}//end Open.

void YuvRawFileHandler::Close(void)
{
  if(_pBuff16 != NULL)
    delete[] _pBuff16;
  _pBuff16    = NULL;

  if(_pBuff8 != NULL)
    delete[] _pBuff8;
  _pBuff8    = NULL;

  _buffLen  = 0;

  RawFileHandlerBase::Close();
}//end Close.

/** Get a ptr to the head of the next yuv unit.
Return the ptr and the length of the next frame/unit
of 16-bit data after the currPos.
@param unitLen  : Total num of pels of the YUV frame in the unit
@return         : Ptr to the head of the unit.
*/
void* YuvRawFileHandler::GetNextUnit(int* unitLen)
{
  if((_pFile == NULL)||((_pBuff16 == NULL)&&(_pBuff8 == NULL)))
  {
    *unitLen = 0;
    return(NULL);
  }//end if _pFile...

  int cnt = 0;

  if(_currPos >= (_length-1)) ///< Wrap around the end.
    _currPos = 0;

  /// From the current pos typecast and copy one full frame of YUV 4:2:0 pels to the buffer.
  if(_inType == YUV4208P)
  {
    if(_outType == YUV42016P)
    {
      for(cnt = 0; (cnt < _buffLen)&&(_currPos < _length); cnt++, _currPos++)
        _pBuff16[cnt] = (short) ((unsigned char *)_pFile)[_currPos];
    }//end if _outType = YUV42016P...
    else if(_outType == YUV4208P)
    {
      for(cnt = 0; (cnt < _buffLen)&&(_currPos < _length); cnt++, _currPos++)
        _pBuff8[cnt] = (unsigned char) ((unsigned char *)_pFile)[_currPos];
    }//end if _outType = YUV4208P...
  }//end else if YUV4208P...
  else if(_inType == YUV420NV12)
  {
    int lumLen = _width * _height;    ///< Y plane.
    int chrLen = lumLen/4;            ///< UV packed.

    if(_outType == YUV42016P)
    {
      /// Lum is planar.
      for(cnt = 0; (cnt < lumLen)&&(_currPos < _length); cnt++, _currPos++)
        _pBuff16[cnt] = (short) ((unsigned char *)_pFile)[_currPos];

      /// Unpack the UV adjacent components into planes.
      for(; (cnt < (lumLen + chrLen))&&(_currPos < _length); cnt++)
      {
        _pBuff16[cnt]           = (short) ((unsigned char *)_pFile)[_currPos++];  ///< U.
        _pBuff16[cnt + chrLen]  = (short) ((unsigned char *)_pFile)[_currPos++];  ///< V.
      }//end for cnt...
      cnt += chrLen;
    }//end if _outType = YUV42016P...
  }//end if YUV420NV12...

  *unitLen = cnt;
  if(_outType == YUV4208P)
    return((void*)( _pBuff8 ));
  return((void*)( _pBuff16 ));
}//end GetNextFrame.

========== END FILE: CodecUtils/YuvRawFileHandler.cpp ==========

========== BEGIN FILE: CodecUtils/YuvRawFileHandler.h ==========
Bundle entry: 140
Original bytes: 3812
Original SHA-256: 79a18ed1092621f4ab6e2b38cf51f7c1583ce6e9cb63261939b5c6136d7f36d5
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: YuvRawFileHandler

TAG						: YUVRFH

FILE NAME			: YuvRawFileHandler.h

DESCRIPTION		: A class to hold raw yuv data used for video codec testing.

COPYRIGHT			:	(c)CSIR 2007-2012 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================================
*/
#ifndef _YuvRawFileHandler_H
#define _YuvRawFileHandler_H

#pragma once

#include "RawFileHandlerBase.h"
/*
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class YuvRawFileHandler : public RawFileHandlerBase
{
public:
	YuvRawFileHandler(void);
	virtual ~YuvRawFileHandler(void);

/// Public interface.
public:

  int   Open(const char* filename, int rw);
  void  Close(void);
  void* GetNextUnit(int* unitLen);

/// Public constants.
public:
	/// Read/In or write/out parameter for Get/PutNextUnit() method.
	static const int YUV4208P	    = 0;
	static const int YUV420NV12   = 1;

	static const int YUV42016P    = 16;

/// Implementation specific interface.
public:

  /// Call these before a call to Open().
  void SetWidth(int width)              { _width = width; }
  void SetHeight(int height)            { _height = height; }
  void SetType(int type)                { _inType = type; }
  void SetType(int intype, int outtype) { _inType = intype; _outType = outtype;}

  void* GetCurrUnit(int* unitLen) { *unitLen = _buffLen; if(_outType == YUV42016P) return((void *)_pBuff16); else return((void *)_pBuff8); }

/// Implementation specific members.
protected:

  short*          _pBuff16;   ///< Units are 16-bit shorts in this implementation.
  unsigned char*  _pBuff8;   ///< Units are 8-bit chars in this implementation.
  int             _buffLen;

  /// YUV 4:2:0 data is stored contiguously as 8/16-bits per component in planar format.
  int     _inType;
  int     _outType; ///< Default = YUV42016P
  int     _width;
  int     _height;

};// end class YuvRawFileHandler.

#endif	//_YuvRawFileHandler_H
========== END FILE: CodecUtils/YuvRawFileHandler.h ==========

========== BEGIN FILE: H264v2/H264v2.cpp ==========
Bundle entry: 141
Original bytes: 1779
Original SHA-256: 0f1ee874c069f091712f27ba8dcd988b24cf41f6787bb4e9e4f7d90390dfeba4
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264

TAG					: H264

FILE NAME			: H264v2.cpp

DESCRIPTION			: H264v2Factory implementation	

LICENSE	: GNU Lesser General Public License

Copyright (c) 2008 - 2012, CSIR
All rights reserved.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/
#include "stdafx.h"
#include "H264v2.h"

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}

H264V2_API H264v2Factory::H264v2Factory(void)
{
}//end constructor.

H264V2_API H264v2Factory::~H264v2Factory(void)
{
}//end destructor.

H264V2_API H264v2Codec* H264v2Factory::GetCodecInstance(void)
{
	return(new H264v2Codec());
}//end GetCodecInstance.

H264V2_API void H264v2Factory::ReleaseCodecInstance(ICodecv2* pInst)
{
	if(pInst != NULL)
	{
		delete pInst;
		pInst = NULL;
	}//end if pInst...
}//end ReleaseCodecInstance.
========== END FILE: H264v2/H264v2.cpp ==========

========== BEGIN FILE: H264v2/H264v2.h ==========
Bundle entry: 142
Original bytes: 2869
Original SHA-256: 6e97f4f52ecbdb6b6c8da0106f891829a9945ab1bc2dee7180f8280b1e72d02d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE:
 
TAG: 

FILE NAME: 

DESCRIPTION: 

COPYRIGHT: (c)CSIR 2007-2018 all rights reserved

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================

*/


// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the H264V2_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// H264V2_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#pragma once

#ifdef _WIN32
#ifdef H264v2_EXPORTS
#define H264V2_API __declspec(dllexport)
#else
#define H264V2_API __declspec(dllimport)
#endif
#else
#define H264V2_API 
#endif

/// This dll has only one purpose to instantiate a H264v2Codec instance. The
/// obligation of scope management is left to the calling functions.
#include "H264v2Codec.h"

// This class is exported from the H264v2.dll
class H264V2_API H264v2Factory 
{
public:
	H264v2Factory(void);
	~H264v2Factory(void);

	/// Interface.
	H264v2Codec* GetCodecInstance(void);
	void ReleaseCodecInstance(ICodecv2* pInst);
};	///end H264v2Factory.
========== END FILE: H264v2/H264v2.h ==========

========== BEGIN FILE: H264v2/stdafx.cpp ==========
Bundle entry: 143
Original bytes: 1262
Original SHA-256: 6629887651cae658ff541159ee243561dc28cb1995fb77228de0cc80376fa0a9
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264

TAG					: H264

FILE NAME			: stdafx.cpp

DESCRIPTION		:	

LICENSE	: GNU Lesser General Public License

Copyright (c) 2008 - 2012, CSIR
All rights reserved.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================*/
#include "stdafx.h"

#include <initguid.h>
#include <uuids.h>
//#include <wmcodecdsp.h> //for i420 GUID

DEFINE_GUID(MEDIASUBTYPE_YUV420P_S, 0xc528b79f, 0xf025, 0x4eb7, 0x92, 0xb0, 0x46, 0xce, 0x81, 0x67, 0xe9, 0xf8);

DEFINE_GUID(MEDIASUBTYPE_I420, 0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
========== END FILE: H264v2/stdafx.cpp ==========

========== BEGIN FILE: H264v2/stdafx.h ==========
Bundle entry: 144
Original bytes: 1074
Original SHA-256: f283ac1f8d303dfe62c4694eb2f21c67c1d53c5e1114484fffabf9cb1cf03fd3
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264

TAG					: H264

FILE NAME			: stdafx.h

DESCRIPTION		:	

LICENSE	: GNU Lesser General Public License

Copyright (c) 2008 - 2012, CSIR
All rights reserved.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/
#pragma once


#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <Windows.h>
========== END FILE: H264v2/stdafx.h ==========

========== BEGIN FILE: H264v2Codec/H264v2Codec.cpp ==========
Bundle entry: 145
Original bytes: 522405
Original SHA-256: cc8b075dcdfc000951ad357355dfaba74c5eba2c308b847c56efaddfcf60bf5d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file
MODULE:		H264v2Codec

TAG:		H264V2

FILE NAME:	H264v2Codec.cpp

DESCRIPTIONS: A 2nd generation of video codecs based on the H264 standard
	      implementation. The primary interface is ICodecv2 for access
	      and configuration.

COPYRIGHT:	(c)CSIR 2007-2017 all rights resevered

LICENSE:	Software License Agreement (BSD License)

RESTRICTIONS: Redistribution and use in source and binary forms, with or without
								modification, are permitted provided that the following conditions
								are met:

								* Redistributions of source code must retain the above copyright notice,
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice,
								this list of conditions and the following disclaimer in the documentation
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used
								to endorse or promote products derived from this software without specific
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================*/

#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <cstdio>
#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include "H264v2Codec.h"

/// Macros
#include "CodecDistortionDef.h"

#include "ConvYUV420_16toRGB.h"
#include "ConvRGB24toYUV420v16FixP.h"
#include "ConvYUV420_16toRGB.h"
//#include "RGBtoYUV420Converter.h"
//#include "YUV420toRGBConverter.h"

#include "IBitStreamWriter.h"
#include "IBitStreamReader.h"
#include "OverlayMem2Dv2.h"
#include "IForwardTransform.h"
#include "IInverseTransform.h"
#include "IRunLengthCodec.h"
#include "VectorStructList.h"
#include "IMotionEstimator.h"
#include "IMotionCompensator.h"
#include "IMotionVectorPredictor.h"
#include "IVlcEncoder.h"
#include "IVlcDecoder.h"
#include "MacroBlockH264.h" 
#include "H264MbImgCache.h"
#include "IRateControl.h"

/// Implementations.
#include "BitStreamWriterMSB.h"
#include "BitStreamReaderMSB.h"
#include "H264BitStreamReader.h"

//#include "RealRGB24toYUV420CCIR601ConverterVer16.h"	// JFO: These converters were intentionally replaced.
//#include "RealYUV420toRGB24CCIR601ConverterVer16.h"	
//#include "RealRGB24toYUV420ConverterImpl2Ver16.h"
//#include "RealYUV420toRGB24ConverterImpl2Ver16.h"

#include "FastForward4x4ITImpl2.h"
#include "FastForward4x4ITImpl1.h"
#include "FastInverse4x4ITImpl1.h"
#include "FastForwardDC4x4ITImpl1.h"
#include "FastInverseDC4x4ITImpl1.h"
#include "FastForwardDC2x2ITImpl1.h"
#include "FastInverseDC2x2ITImpl1.h"
#include "FastForward4x4On16x16ITImpl1.h"
#include "FastInverse4x4On16x16ITImpl1.h"
#include "CAVLCH264Impl.h"
#include "CAVLCH264Impl2.h"

#include "MotionEstimatorH264ImplMultires.h"
#include "MotionEstimatorH264ImplMultiresCross.h"
#include "MotionEstimatorH264ImplCross.h"
#include "MotionEstimatorH264ImplMultiresCrossVer2.h"
#include "MotionEstimatorH264ImplFull.h"
#include "MotionEstimatorH264ImplTest.h"
#include "MotionCompensatorH264ImplStd.h"
#include "H264MotionVectorPredictorImpl1.h"


#include "PrefixH264VlcEncoderImpl1.h"
#include "PrefixH264VlcDecoderImpl1.h"
#include "CoeffTokenH264VlcEncoder.h"
#include "CoeffTokenH264VlcDecoder.h"
#include "TotalZeros4x4H264VlcEncoder.h"
#include "TotalZeros4x4H264VlcDecoder.h"
#include "TotalZeros2x2H264VlcEncoder.h"
#include "TotalZeros2x2H264VlcDecoder.h"
#include "TotalZeros2x4H264VlcEncoder.h"
#include "TotalZeros2x4H264VlcDecoder.h"
#include "RunBeforeH264VlcEncoder.h"
#include "RunBeforeH264VlcDecoder.h"
#include "ExpGolombUnsignedVlcEncoder.h"
#include "ExpGolombUnsignedVlcDecoder.h"
#include "ExpGolombSignedVlcEncoder.h"
#include "ExpGolombSignedVlcDecoder.h"
#include "ExpGolombTruncVlcEncoder.h"
#include "ExpGolombTruncVlcDecoder.h"
#include "CodedBlkPatternH264VlcEncoder.h"
#include "CodedBlkPatternH264VlcDecoder.h"

#include "RateControlImplQuad.h"
#include "RateControlImplPow.h"
#include "RateControlImplLog.h"
//#include "RateControlImplMultiModel.h"  An incomplete work in progress.

/*
---------------------------------------------------------------------------
  Codec parameter constants.
---------------------------------------------------------------------------
*/
/// Picture type definitions. Values for _pictureCodingType member.
#define H264V2_INTRA				0
#define H264V2_INTER				1
#define H264V2_SEQ_PARAM		2
#define H264V2_PIC_PARAM		3

#define H264V2_I_PIC				0
#define H264V2_P_PIC				1
#define H264V2_PB_PIC				2
#define H264V2_B_PIC				3
#define H264V2_EI_PIC				4
#define H264V2_EP_PIC				5

#define H264V2_MAX_QP							  51	///< Maximum QP value
#define H264V2_MAX_EXT_QP	          71	///< Maximum extended QP value for Inter
#define H264V2_I_MAX_EXT_QP	        85	///< Maximum extended QP value for Intra

#define H264V2_MAX_INTRA_ITERATIONS	5 	///< Default settings for a limit on optimisation iterations for slow convergence.
#define H264V2_MAX_INTER_ITERATIONS	10 

/*
---------------------------------------------------------------------------
  Colour space constants.
---------------------------------------------------------------------------
*/
#define H264V2_RGB24							0		///< 888 (Default).
#define H264V2_RGB32							1		///< 8888.
#define H264V2_RGB16							2		///< 565.

#define H264V2_YUV420P16					16	///< Planar Y, U then V (16 bits/component).
#define H264V2_YUV420P8						17	///< Planar Y, U then V (8 bits/component).

/*
--------------------------------------------------------------------------
  Macros.
--------------------------------------------------------------------------
*/
#define H264V2_CLIP31(x)	( (((x) <= 31)&&((x) >= 1))? (x) : ( ((x) < 1)? 1:31 ) )
#define H264V2_CLIP51(x)	( (((x) <= 31)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:51 ) )
#define H264V2_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

#undef	H264V2_EXACT_DMAX

#define H264V2_FAST_ABS32(x) ( ((x)^((x)>>31))-((x)>>31) )
#define H264V2_FAST_ABS16(x) ( ((x)^((x)>>15))-((x)>>15) )

/*
--------------------------------------------------------------------------
  Local constants.
--------------------------------------------------------------------------
*/
const int		H264v2Codec::PARAMETER_LEN = 36;
const char*	H264v2Codec::PARAMETER_LIST[] =
{
	"parameters",								            // 0
	"codecid",									            // 1
	"width",										            // 2
	"height",										            // 3
	"incolour",									            // 4
	"outcolour",								            // 5
  "flip",                                 // 6
	"picture coding type",			            // 7
	"last pic coding type",			            // 8
	"quality",									            // 9
	"autoipicture",							            // 10 
	"ipicturemultiplier",				            // 11
	"ipicturefraction",					            // 12
	"mode of operation",				            // 13
	"intra iteration limit",				        // 14
	"inter iteration limit",				        // 15
	"time limit msec",				              // 16
  "rate control model type",              // 17
	"seq param set",						            // 18
	"pic param set",						            // 19
	"gen param set on open",		            // 20
  "prepend param sets to i-pictures",     // 21
	"start code emulation prevention",      // 22
  "idr frame number",                     // 23
  "p frame number",                       // 24
  "seq param log2 max frame num minus 4", // 25
  "minimum intra qp",                     // 26
  "minimum intra qp",                     // 27
  "max distortion",                       // 28
  "num rate control frames",              // 29
  "max bits per frame",                   // 30
  "ipicture dmax multiplier",             // 31
  "ipicture dmax fraction",               // 32
  "rate overshoot percent",               // 33
  "enable roi encoding",                  // 34
  "input framing"                         // 35
};

const int		H264v2Codec::MEMBER_LEN = 7;
const char*	H264v2Codec::MEMBER_LIST[] =
{
	"members",									// 0
	"macroblocks",							// 1
  "reference",                // 2
	"autoiframedetectflag",			// 3
  "roi multiplier",			      // 4
  "currseqparamset",          // 5
  "currpicparamset"           // 6
};

/// Scaling is required for the DC coeffs to match the 4x4 
/// inverse IT scaling of the AC coeffs. Standard defines 
/// default Flat_4x4_16 for DC scaling.
const int H264v2Codec::dc4x4Scale[16] =
{ 16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16
};
const int H264v2Codec::dc2x2Scale[4] =
{ 16, 16,
	16, 16
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a grid defined by the method used in 
/// the Packet Video Conference Proceedings 2015 in a paper by K.T. Luhandjula and K.L. Ferguson entitled "Sampling 
/// Point Path Selection for Fast Intra Mode Prediction".
#define H264V2_16x16_PATH_LENGTH 20

const int H264v2Codec::testPntPath16xy[256][2] =
{
  {10,10},{7,5},{13,14},{3,12},{12,3},{5,8},{15,6},{7,13},{2,3},{10,1},{1,9},{12,9},{5,15},{6,2},{14,11},{9,7}, ///< 0-15
  {2,6},{14,2},{8,12},{4,4},{1,14},{11,6},{11,15},{5,0},{7,10},{0,11},{9,4},{15,10},{13,5},{4,7},{3,1},{10,13}, ///< 16-31
  {12,0},{4,11},{0,3},{8,8},{8,2},{3,14},{15,14},{6,7},{1,5},{12,12},{14,4},{3,9},{6,12},{13,7},{11,1},{0,7},   ///< 32-47
  {9,9},{5,4},{9,15},{2,10},{11,8},{4,0},{9,3},{1,12},{14,9},{7,1},{5,13},{15,1},{10,11},{0,2},{3,4},{13,15},   ///< 48-63
  {10,5},{7,14},{5,10},{12,2},{2,8},{13,11},{8,6},{0,14},{1,1},{15,8},{7,3},{9,0},{3,6},{11,12},{4,15},{14,3},  ///< 64-79
  {6,10},{14,13},{6,6},{10,7},{0,9},{4,2},{12,6},{8,14},{2,13},{2,0},{13,9},{9,8},{1,3},{6,1},{4,12},{6,4},     ///< 80-95
  {2,5},{11,11},{15,13},{1,11},{10,2},{1,4},{14,5},{8,11},{10,15},{3,8},{7,0},{0,6},{2,15},{15,0},{5,3},{14,8}, ///< 96-111
  {6,11},{12,14},{9,5},{7,7},{4,10},{9,13},{13,4},{11,9},{3,3},{4,6},{0,12},{5,1},{6,14},{14,12},{15,2},{9,10}, ///< 112-127
  {7,2},{1,7},{12,8},{4,9},{8,3},{3,13},{10,0},{12,5},{7,9},{15,7},{11,13},{7,15},{1,2},{5,6},{13,10},{11,3},   ///< 128-143
  {2,11},{15,15},{0,0},{1,15},{2,1},{10,6},{8,4},{5,12},{12,11},{11,0},{4,8},{9,8},{1,3},{6,1},{13,3},{13,13},  ///< 144-159
  {5,9},{9,12},{2,7},{15,4},{0,13},{9,14},{6,0},{3,5},{2,14},{13,6},{15,9},{8,5},{0,5},{11,10},{14,1},{3,7},    ///< 160-175
  {14,10},{8,13},{5,14},{3,2},{9,1},{1,10},{6,3},{11,7},{7,11},{12,15},{13,2},{2,9},{8,9},{10,4},{6,13},{4,1},  ///< 176-191
  {13,2},{2,9},{8,9},{10,4},{6,13},{4,1},{10,12},{0,8},{2,2},{3,11},{0,1},{10,8},{5,5},{14,7},{8,0},{0,10},     ///< 192-207
  {4,13},{6,5},{15,11},{11,2},{11,14},{8,7},{0,4},{8,10},{6,15},{13,12},{10,3},{7,4},{4,14},{1,8},{3,0},{12,7}, ///< 208-223
  {12,1},{5,11},{9,6},{4,3},{6,9},{4,5},{1,13},{15,12},{9,2},{10,14},{12,4},{1,0},{2,12},{10,9},{15,3},{5,2},   ///< 224-239
  {7,12},{14,14},{0,15},{13,8},{3,10},{14,0},{5,7},{9,11},{11,5},{1,6},{8,15},{8,1},{2,4},{12,13},{14,6},{6,8}  ///< 240-255
};
/*
const int H264v2Codec::testPntPath16xy[256][2] =
  {
	{0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},{0,12},{0,13},{0,14},{0,15}, ///< 0-15
	{1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},{1,12},{1,13},{1,14},{1,15}, ///< 16-31
	{2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},{2,12},{2,13},{2,14},{2,15}, ///< 32-47
	{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11},{3,12},{3,13},{3,14},{3,15}, ///< 48-63
	{4,0},{4,1},{4,2},{4,3},{4,4},{4,5},{4,6},{4,7},{4,8},{4,9},{4,10},{4,11},{4,12},{4,13},{4,14},{4,15}, ///< 64-79
	{5,0},{5,1},{5,2},{5,3},{5,4},{5,5},{5,6},{5,7},{5,8},{5,9},{5,10},{5,11},{5,12},{5,13},{5,14},{5,15}, ///< 80-95
	{6,0},{6,1},{6,2},{6,3},{6,4},{6,5},{6,6},{6,7},{6,8},{6,9},{6,10},{6,11},{6,12},{6,13},{6,14},{6,15}, ///< 96-111
	{7,0},{7,1},{7,2},{7,3},{7,4},{7,5},{7,6},{7,7},{7,8},{7,9},{7,10},{7,11},{7,12},{7,13},{7,14},{7,15}, ///< 112-127
	{8,0},{8,1},{8,2},{8,3},{8,4},{8,5},{8,6},{8,7},{8,8},{8,9},{8,10},{8,11},{8,12},{8,13},{8,14},{8,15}, ///< 128-143
	{9,0},{9,1},{9,2},{9,3},{9,4},{9,5},{9,6},{9,7},{9,8},{9,9},{9,10},{9,11},{9,12},{9,13},{9,14},{9,15}, ///< 144-159
	{10,0},{10,1},{10,2},{10,3},{10,4},{10,5},{10,6},{10,7},{10,8},{10,9},{10,10},{10,11},{10,12},{10,13},{10,14},{10,15}, ///< 160-175
	{11,0},{11,1},{11,2},{11,3},{11,4},{11,5},{11,6},{11,7},{11,8},{11,9},{11,10},{11,11},{11,12},{11,13},{11,14},{11,15}, ///< 176-191
	{12,0},{12,1},{12,2},{12,3},{12,4},{12,5},{12,6},{12,7},{12,8},{12,9},{12,10},{12,11},{12,12},{12,13},{12,14},{12,15}, ///< 192-207
	{13,0},{13,1},{13,2},{13,3},{13,4},{13,5},{13,6},{13,7},{13,8},{13,9},{13,10},{13,11},{13,12},{13,13},{13,14},{13,15}, ///< 208-223
	{14,0},{14,1},{14,2},{14,3},{14,4},{14,5},{14,6},{14,7},{14,8},{14,9},{14,10},{14,11},{14,12},{14,13},{14,14},{14,15}, ///< 224-239
	{15,0},{15,1},{15,2},{15,3},{15,4},{15,5},{15,6},{15,7},{15,8},{15,9},{15,10},{15,11},{15,12},{15,13},{15,14},{15,15}  ///< 240-255
  };
*/

#define H264V2_8x8_PATH_LENGTH 5

const int H264v2Codec::testPntPath8xy[64][2] =
{
  {5,5},{3,3},{7,7},{2,6},{6,1},{2,4},{7,3},{3,6},    ///< 0-7
  {1,2},{5,0},{0,4},{6,4},{2,7},{3,1},{7,5},{4,3},    ///< 8-15
  {1,3},{7,1},{4,6},{2,2},{0,7},{5,3},{5,7},{2,0},    ///< 16-23
  {3,5},{0,5},{4,2},{7,4},{6,2},{2,3},{1,0},{5,6},    ///< 24-31
  {6,0},{0,1},{4,4},{4,1},{1,7},{6,6},{3,4},{0,2},    ///< 32-39
  {6,5},{7,2},{1,4},{3,7},{6,3},{5,1},{0,3},{4,5},    ///< 40-47
  {3,2},{4,7},{1,5},{5,4},{2,1},{5,2},{0,6},{7,6},    ///< 48-55
  {3,0},{2,5},{7,0},{6,7},{1,1},{0,0},{4,0},{1,6}     ///< 56-63
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a spread out grid.
const int H264v2Codec::test16X[256] = { 3, 11,  3, 11,
									1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,
									3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,
									0,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,
									5,  9, 13,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  5,  9, 13,
									1,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  0,  3, 11, 15,  6, 14,  0,  1,  9, 15,  0,  3, 11, 15,  0,  3, 11, 15,  0,  1, 15,  6, 14,  0,  9, 15,  0,  3, 11, 15,  1,  2,  4,  6,  8, 10, 12, 14,
									2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,
									1,  5,  7,  9, 13,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13,  1,  5,  7,  9, 13,  3,  5,  7,  9, 11, 13,  1,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13 };
const int H264v2Codec::test16Y[256] = { 3,  3, 11, 11,
									1,  1,  1,  1,  5,  5,  5,  5,  9,  9,  9,  9, 13, 13, 13, 13,
									0,  0,  0,  0,  3,  3,  3,  7,  7,  7,  7,  7, 11, 11, 11, 15, 15, 15, 15, 15,
									0,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  6, 10, 10, 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14,
									0,  0,  0,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 15, 15, 15,
									0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,  8,  8,  8,  8, 10, 10, 10, 11, 11, 12, 12, 12, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
									1,  1,  1,  1,  1,  1,  1,  3,  3,  3,  3,  3,  5,  5,  5,  5,  5,  5,  5,  7,  7,  7,  7,  7,  7,  7,  9,  9,  9,  9,  9,  9,  9, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13,
									2,  2,  2,  2,  2,  4,  4,  4,  4,  4,  6,  6,  6,  6,  6,  8,  8,  8,  8,  8, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14 };
const int H264v2Codec::test16Limit[8] = { 4, 20, 40, 69, 123, 174, 219, 256 };

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a zooming square grid to be 
/// used 4 at a time where {(0,0), (0,8), (8,0), (8,8)} is added to each address in the table.
const int H264v2Codec::testZoom16X[21] =
{ 3,
  1, 5, 1, 5,
  0, 4, 0, 4,
  2, 6, 2, 6,
  0, 4, 0, 4,
  2, 6, 2, 6
};
const int H264v2Codec::testZoom16Y[21] =
{ 3,
  1, 1, 5, 5,
  0, 0, 4, 4,
  0, 0, 4, 4,
  2, 2, 6, 6,
  2, 2, 6, 6
};
const int H264v2Codec::testZoom16Len = 21;
const int H264v2Codec::delta16[4][2] = { {0,0}, {8,0}, {0,8}, {8,8} };
///< Thresholds for predicted final distortion = 20480/(256/4) = 320 (4 samples/mode completed)
#define H264V2_LUM_DISTORTION_THRESHOLD 320

const int H264v2Codec::testZoom8[5][2] = { {3,3}, {1,1}, {5,1}, {1,5}, {5,5} };
const int H264v2Codec::testZoom8Len = 5;
///< Thresholds for predicted final distortion = 10240/(128/2) = 160 (2 samples/mode completed)
#define H264V2_CHR_DISTORTION_THRESHOLD 160

/// Test sampling point coordinates for Intra_8x8 prediction mode selection.
const int H264v2Codec::test8X[64] = { 2, 5, 2, 5,
																			0, 4, 7, 0, 7, 0, 4, 7,
																			2, 5, 6, 1, 6, 0, 7, 3, 4, 3, 4, 0, 7, 1, 6, 2, 5,
																			1, 3, 0, 2, 3, 4, 5, 7, 1, 3, 4, 6, 0, 1, 2, 5, 6, 7, 1, 2, 5, 6, 1, 3, 4, 6, 0, 2, 3, 4, 5, 7, 1, 3, 6 };
const int H264v2Codec::test8Y[64] = { 2, 2, 5, 5,
																			0, 0, 0, 4, 4, 7, 7, 7,
																			0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
																			0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7 };
const int H264v2Codec::test8Limit[4] = { 4, 12, 29, 64 };

/// Loop filter constants.
const int H264v2Codec::alpha[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226, 255, 255 };
const int H264v2Codec::beta[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3,  4,  4,  4,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13,  14,  14,  15,  15,  16,  16,  17,  17,  18,  18 };
///                                           0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
const int H264v2Codec::indexAbS[3][52] = { { 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, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 8,10,11,12,13,15,17 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13,14,16,18,20,23,25} };

/// Fast search on the macroblock distortion vs. QP curve changes the step size
/// depending on the QP value.
#ifdef H264V2_EXACT_DMAX
const int H264v2Codec::MbStepSize[H264V2_MAX_QP + 1] =
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
#else
const int H264v2Codec::MbStepSize[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	 1,	 1,	 1,	 2,	 2,	 2,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 3,	 3,	 3,	 3,	 3,	 3,	 3,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		3,	 3,	 3,	 3,	 3,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		4,	 4,	 4,	 4,  1,  2,  3,  4,  1,  2,  3,  4,  1,  2,  3,  4,
//  64  65  66  67  68  69  70  71
    1,   1,  1,  1,  1,  1,  1,  1
};
#endif
const int H264v2Codec::NextQPDec[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	2,	3,	4,	5,	6,	7,	8,	 9,	10,	11,	11,	13,	13,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		15,	15,	17,	17,	19,	19,	21,	21,	23,	23,	25,	25,	27,	27,	29,	29,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		31,	31,	31,	31,	35,	35,	35,	35,	39,	39,	39,	39,	43,	43,	43,	43,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		47,	47,	47,	47, 51, 51, 51, 51, 55, 55, 55, 55, 59, 59, 59, 59,
//  64  65  66  67  68  69  70  71
		63, 63, 63, 63, 67, 68, 69, 70
};

/// CPU speed dependent high resolution timer.
double H264v2Codec::_cpuFreq = 0.0;

/// Motion lambda constants for TCP-like adaptation.
const double H264v2Codec::MVLAMBDA_MAX          = 4.0;
const double H264v2Codec::MVLAMBDA_STEP         = -0.1;
const double H264v2Codec::MVLAMBDA_MULT         = 0.5;
const double H264v2Codec::MVLAMBDA_STEADYSTATE  = 0.9;

/*
--------------------------------------------------------------------------
  Construction and destruction.
--------------------------------------------------------------------------
*/

H264v2Codec::H264v2Codec()
{
    _inputFraming = 0; // Legacy Annex-B input by default.

	ResetMembers();
}//end constructor.

void H264v2Codec::ResetMembers(void)
{
#ifdef H264V2_DUMP_HEADERS
	_headerTableLen = 300;
	_headerTable.Create(6, _headerTableLen);

	_headerTable.SetHeading(0, "NALType");
	_headerTable.SetHeading(1, "NALRefIdc");
	_headerTable.SetHeading(2, "IdrPicId");
	_headerTable.SetHeading(3, "FrmNum");
	_headerTable.SetHeading(4, "SliceType");
	_headerTable.SetHeading(5, "Qp");

	for (int j = 0; j < 6; j++)
		_headerTable.SetDataType(j, MeasurementTable::INT);

	_headerTablePos = 0;
#endif /// H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	int j;
	/// Collect macroblock R or D values for each QP for 64 macroblocks.
	_mbRDTableLen = 53;
	_mbRDTable.Create(65, _mbRDTableLen);  /// 1 for QP and 1 D value per mb

	_mbRDTable.SetHeading(0, "QP");
	_mbRDTable.SetHeading(1, "Distortion");
	for (j = 2; j < 65; j++)
		_mbRDTable.SetHeading(j, " ");

	for (j = 0; j < 65; j++)
		_mbRDTable.SetDataType(j, MeasurementTable::INT);

	/// 1st column is QP value for all mbs.
	_mbRDTable.WriteItem(0, 0, 0);
	for (j = 1; j < _mbRDTableLen; j++)
		_mbRDTable.WriteItem(0, j, j);

	_mbRDTablePos = 1;
#endif /// H264V2_DUMP_MB_RD_DATA
#ifdef H264V2_DUMP_TIMING
	_timingTableLen = 300;
	_timingTable.Create(2, _timingTableLen);

	_timingTable.SetHeading(0, "Frame");
	_timingTable.SetHeading(1, "Time (ms)");

	_timingTable.SetDataType(0, MeasurementTable::INT);
	_timingTable.SetDataType(1, MeasurementTable::INT);

	_timingTablePos = 0;
#endif /// H264V2_DUMP_TIMING

	_errorStr = "[H264v2Codec::ResetMembers] No error";
	_codecIsOpen = 0;
	_bitStreamSize = 0;

	/// Set default parameter values.
	_idCode = (int)H264V2_ID;
	_width = 176;
	_height = 144;
	_inColour = H264V2_RGB24;	///< Default to 24 bit rgb.
	_outColour = H264V2_RGB24;
	_flip = false;
	_pictureCodingType = H264V2_INTRA;
	_lastPicCodingType = H264V2_INTRA;
	_pQuant = 26;		///< Mid range [1..51].
	_minQPIntra = 16;   ///< Min QP value during mb optimisation
	_minQPInter = 4;
	_autoIPicture = 1;
	_iPictureMultiplier = 1;
	_iPictureFraction = 0;
	_iPictureDMaxMultiplier = 2;
	_iPictureDMaxFraction = 0;
	_dMax = 30000;    ///< Max distortion for all mbs with modeOfOperation = H264V2_MB_QP_DMAX_ADAPTIVE.
	_maxBitsPerFrame = 100240;   ///< This defines the max bit limit for modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_numRateCntlFrames = 12;     ///< Num of frames to do avg rate adaption over with  modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_rateOvershootPercent = 100;   ///< Percentage that the avg rate can be exceeded from frame to frame. 
	_coeffBitsPerPel = 0.0001;

	_modeOfOperation = H264V2_OPEN;
	_intraIterations = H264V2_MAX_INTRA_ITERATIONS;    ///< Intra optimisation iteration limit.
	_interIterations = H264V2_MAX_INTER_ITERATIONS;    ///< Inter optimisation iteration limit.
	_timeLimitMs = 0;  ///< Intra/inter optimisation time limit.
	_rateControlModelType = H264V2_RATE_CONTROL_MODEL_LOG;  ///< For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE.

	_currSeqParam = 0;	///< Index reference into _seqParam[32] array.
	_currPicParam = 0;	///< Index reference into _picParam[2] array.
	_genParamSetOnOpen = 1;	///< Generate the seq/pic parameter sets on the Open() call.
	_prependParamSetsToIPic = 1;  ///< Prepend a SPS and PPS NAL unit to the front of every I-Picture.

	_startCodeEmulationPrevention = 1;  ///< Enable/disable start code emulation prevention in bit stream.

	/// Work input image.
	_lumWidth = 0;
	_lumHeight = 0;
	_pLum = NULL;
	_chrWidth = 0;
	_chrHeight = 0;
	_pChrU = NULL;
	_pChrV = NULL;
	_Lum = NULL;
	_Cb = NULL;
	_Cr = NULL;
	/// Reference images.
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;
	_RefLum = NULL;
	_RefCb = NULL;
	_RefCr = NULL;

	/// Temp work mem.
	_p16x16 = NULL;
	_16x16 = NULL;
	_p8x8_0 = NULL;
	_8x8_0 = NULL;
	_p8x8_1 = NULL;
	_8x8_1 = NULL;

	/// Cache
	_mbImg = NULL;

	/// Colour converters.
	_pInColourConverter = NULL;
	_pOutColourConverter = NULL;
	/// Stream access.
	_pBitStreamWriter = NULL;
	_pBitStreamReader = NULL;
	/// IT transform filters.
	_pF4x4TLum = NULL;
	_pF4x4TChr = NULL;
	_pFDC4x4T = NULL;
	_pFDC2x2T = NULL;
	_pI4x4TLum = NULL;
	_pI4x4TChr = NULL;
	_pIDC4x4T = NULL;
	_pIDC2x2T = NULL;

	/// For motion estimation (and compensation).
	_motionFactor             = 2; ///< Default for abs diff algorithms.
	_prevMotionDistortion     = -1;
	_autoIFrameIncluded       = NULL;
	_pMotionEstimator         = NULL;
	_pMotionEstimationResult  = NULL;
	_pMotionCompensator       = NULL;
	_pMotionVectors           = NULL;
	_pMotionPredictor         = NULL;

	/// Vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = NULL;
	_pPrefixVlcDec = NULL;
	_pCoeffTokenVlcEnc = NULL;
	_pCoeffTokenVlcDec = NULL;
	_pTotalZeros4x4VlcEnc = NULL;
	_pTotalZeros4x4VlcDec = NULL;
	_pTotalZeros2x2VlcEnc = NULL;
	_pTotalZeros2x2VlcDec = NULL;
	_pRunBeforeVlcEnc = NULL;
	_pRunBeforeVlcDec = NULL;
	/// ... and the remaining vlc encoders and decoders.
	_pBlkPattVlcEnc = NULL;
	_pBlkPattVlcDec = NULL;
	_pDeltaQPVlcEnc = NULL;
	_pDeltaQPVlcDec = NULL;
	_pMbTypeVlcEnc = NULL;
	_pMbTypeVlcDec = NULL;
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	/// The CAVLC codecs.
	_pCAVLC4x4 = NULL;
	_pCAVLC2x2 = NULL;
	/// General header vlc encoders and decoders.
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// Macroblock data objects.
	_pMb = NULL;
	_Mb = NULL;

	/// Internal parameters.

	  /// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	  /// control parameters to maintain a list of these references. However, in this implementation
	  /// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	  /// reference lists (List0) are maintained and frame number counting is consecutively incremented
	  /// from the previous IDR-frame.
	_seqParamSetLog2MaxFrameNumMinus4 = 12;         ///< Range [0..12] made available as a codec parameter.
	_frameNum = 0;				  ///< Used for SliceHeader._frame_num
	_maxFrameNum = 1 << (_seqParamSetLog2MaxFrameNumMinus4 + 4);	///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	_idrFrameNum = 0;				  ///< Used for SliceHeader._idr_pic_id

	/// Slice without partitioning and therefore the slice parameters are simple. (Only one slice/frame.)
	_slice._type = SliceHeaderH264::I_Slice_All;	///< I-Slice/P-Slice.
	_slice._qp = _pQuant;	                    ///< Same as _pQuant for this implementation.
	_slice._qp_delta = 0;				                    ///< = 0 for this implementation.
	_slice._disable_deblocking_filter_idc = 0;
	_mb_skip_run = 0;				                    ///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders.
	_pIntraImgPlaneEncoder = NULL;
	_pInterImgPlaneEncoder = NULL;
	_pIntraImgPlaneDecoder = NULL;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	_pRateCntlPFrames = NULL;
	_pRateCntlIFrames = NULL;
  
  /// Region of Interest encoding.
  _roiMultiplier      = NULL;
  _enableROIEncoding  = 0; ///< Default is off.

	/// Motion vector Le Grange multiplier adaptation.
	_mvLambda = MVLAMBDA_STEADYSTATE;

	/// Timer
	_startTime = 0;

}//end ResetMembers.

H264v2Codec::~H264v2Codec()
{
	// If open then close first before exiting.
	if (_codecIsOpen)
		Close();
}//end destructor.

/*
-----------------------------------------------------------------------
  Parameter interface functions.
-----------------------------------------------------------------------
*/
int	H264v2Codec::GetParameter(const char* type, int*	length, void*	value)
{
    if(type && _stricmp(type, "input framing") == 0)
    {
        strcpy((char*)value, _inputFraming ? "avc1" : "annexb");
        *length = (int)strlen((char*)value);
        return 1;
    }


	char *p = (char *)type;
	int len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		//_itoa(_pictureCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _pictureCodingType);
	else if (strncmp(p, "last pic coding type", len) == 0)
		//_itoa(_lastPicCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _lastPicCodingType);
	else if (strncmp(p, "idr frame number", len) == 0)
		//_itoa(_idrFrameNum,(char *)value,10);
		sprintf((char *)value, "%d", _idrFrameNum);
	else if (strncmp(p, "p frame number", len) == 0)
		//_itoa(_frameNum,(char *)value,10);
		sprintf((char *)value, "%d", _frameNum);
	else if (strncmp(p, "width", len) == 0)
		//_itoa(_width,(char *)value,10);
		sprintf((char *)value, "%d", _width);
	else if (strncmp(p, "height", len) == 0)
		//_itoa(_height,(char *)value,10);
		sprintf((char *)value, "%d", _height);
	else if (strncmp(p, "incolour", len) == 0)
		//_itoa(_inColour,(char *)value,10);
		sprintf((char *)value, "%d", _inColour);
	else if (strncmp(p, "outcolour", len) == 0)
		//_itoa(_outColour,(char *)value,10);
		sprintf((char *)value, "%d", _outColour);
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = _flip ? 1 : 0;
		sprintf((char *)value, "%d", i);
	}
	else if (strncmp(p, "quality", len) == 0)
		//_itoa(_pQuant,(char *)value,10);
		sprintf((char *)value, "%d", _pQuant);
	else if (strncmp(p, "autoipicture", len) == 0)
		//_itoa(_autoIPicture,(char *)value,10);
		sprintf((char *)value, "%d", _autoIPicture);
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		//_itoa(_iPictureMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureMultiplier);
	else if (strncmp(p, "ipicturefraction", len) == 0)
		//_itoa(_iPictureFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureFraction);
	else if (strncmp(p, "codecid", len) == 0)
		//_itoa(_idCode,(char *)value,10);
		sprintf((char *)value, "%d", _idCode);
	else if (strncmp(p, "mode of operation", len) == 0)
		//_itoa(_modeOfOperation,(char *)value,10);
		sprintf((char *)value, "%d", _modeOfOperation);
	else if (strncmp(p, "intra iteration limit", len) == 0)
		//_itoa(_intraIterations,(char *)value,10);
		sprintf((char *)value, "%d", _intraIterations);
	else if (strncmp(p, "inter iteration limit", len) == 0)
		//_itoa(_interIterations,(char *)value,10);
		sprintf((char *)value, "%d", _interIterations);
	else if (strncmp(p, "time limit msec", len) == 0)
		//_itoa(_timeLimitMs,(char *)value,10);
		sprintf((char *)value, "%d", _timeLimitMs);
	else if (strncmp(p, "rate control model type", len) == 0)
		//_itoa(_rateControlModelType,(char *)value,10);
		sprintf((char *)value, "%d", _rateControlModelType);
	else if (strncmp(p, "seq param set", len) == 0)
		//_itoa(_currSeqParam,(char *)value,10);
		sprintf((char *)value, "%d", _currSeqParam);
	else if (strncmp(p, "pic param set", len) == 0)
		//_itoa(_currPicParam,(char *)value,10);
		sprintf((char *)value, "%d", _currPicParam);
	else if (strncmp(p, "generate param set on open", len) == 0)
		//_itoa(_genParamSetOnOpen,(char *)value,10);
		sprintf((char *)value, "%d", _genParamSetOnOpen);
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		//_itoa(_prependParamSetsToIPic,(char *)value,10);
		sprintf((char *)value, "%d", _prependParamSetsToIPic);
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		//_itoa(_startCodeEmulationPrevention,(char *)value,10);
		sprintf((char *)value, "%d", _startCodeEmulationPrevention);
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		//_itoa(_seqParamSetLog2MaxFrameNumMinus4,(char *)value,10);
		sprintf((char *)value, "%d", _seqParamSetLog2MaxFrameNumMinus4);
	else if (strncmp(p, "minimum intra qp", len) == 0)
		//_itoa(_minQPIntra,(char *)value,10);
		sprintf((char *)value, "%d", _minQPIntra);
	else if (strncmp(p, "minimum inter qp", len) == 0)
		//_itoa(_minQPInter,(char *)value,10);
		sprintf((char *)value, "%d", _minQPInter);
	else if (strncmp(p, "max distortion", len) == 0)
		//_itoa(_dMax,(char *)value,10);
		sprintf((char *)value, "%d", _dMax);
	else if (strncmp(p, "num rate control frames", len) == 0)
		//_itoa(_numRateCntlFrames,(char *)value,10);
		sprintf((char *)value, "%d", _numRateCntlFrames);
	else if (strncmp(p, "max bits per frame", len) == 0)
		//_itoa(_maxBitsPerFrame,(char *)value,10);
		sprintf((char *)value, "%d", _maxBitsPerFrame);
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		//_itoa(_iPictureDMaxMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxMultiplier);
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		//_itoa(_iPictureDMaxFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxFraction);
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		//_itoa(_rateOvershootPercent,(char *)value,10);
		sprintf((char *)value, "%d", _rateOvershootPercent);
  else if (strncmp(p, "enable roi encoding", len) == 0)
    sprintf((char *)value, "%d", _enableROIEncoding);
  else if (strncmp(p, "parameters", len) == 0)
		//_itoa(PARAMETER_LEN,(char *)value,10);
		sprintf((char *)value, "%d", PARAMETER_LEN);
	else
	{
		_errorStr = "[H264v2Codec::GetParameter] Read parameter not supported";
		return(0);
	}//end else...

	*length = (int)strlen((char *)value);
	return(1);

	return(0);
}//end GetParameter.

void H264v2Codec::GetParameterName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= PARAMETER_LEN))
		return;
	*name = (const char *)PARAMETER_LIST[ordinal];
	*length = (int)strlen(PARAMETER_LIST[ordinal]);

}//end GetParameterName.

int H264v2Codec::SetParameter(const char* type, const char* value)
{
    if(type && _stricmp(type, "input framing") == 0)
    {
        if(value && (_stricmp(value, "annexb") == 0 || strcmp(value, "0") == 0))
            _inputFraming = 0;
        else if(value && (_stricmp(value, "avc1") == 0 || strcmp(value, "1") == 0))
            _inputFraming = 1;
        else
        {
            _errorStr = "[H264v2Codec::SetParameter] input framing must be annexb or avc1";
            return 0;
        }
        return 1;
    }

	char *p = (char *)type;
	char *v = (char *)value;
	int  len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		_pictureCodingType = (int)(atoi(v));
	else if (strncmp(p, "idr frame number", len) == 0)
		_idrFrameNum = (int)(atoi(v));
	else if (strncmp(p, "p frame number", len) == 0)
		_frameNum = (int)(atoi(v));
	else if (strncmp(p, "width", len) == 0)
		_width = (int)(atoi(v));
	else if (strncmp(p, "height", len) == 0)
		_height = (int)(atoi(v));
	else if (strncmp(p, "incolour", len) == 0)
		_inColour = (int)(atoi(v));
	else if (strncmp(p, "outcolour", len) == 0)
		_outColour = (int)(atoi(v));
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = (atoi)(v);
		_flip = (i != 0);
	}
	else if (strncmp(p, "quality", len) == 0)
		_pQuant = (int)(atoi(v));
	else if (strncmp(p, "autoipicture", len) == 0)
		_autoIPicture = (int)(atoi(v));
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		_iPictureMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicturefraction", len) == 0)
		_iPictureFraction = (int)(atoi(v));
	else if (strncmp(p, "mode of operation", len) == 0)
		_modeOfOperation = (int)(atoi(v));
	else if (strncmp(p, "intra iteration limit", len) == 0)
		_intraIterations = (int)(atoi(v));
	else if (strncmp(p, "inter iteration limit", len) == 0)
		_interIterations = (int)(atoi(v));
	else if (strncmp(p, "time limit msec", len) == 0)
		_timeLimitMs = (int)(atoi(v));
	else if (strncmp(p, "rate control model type", len) == 0)
		_rateControlModelType = (int)(atoi(v));
	else if (strncmp(p, "seq param set", len) == 0)
		_currSeqParam = (int)(atoi(v));
	else if (strncmp(p, "pic param set", len) == 0)
		_currPicParam = (int)(atoi(v));
	else if (strncmp(p, "generate param set on open", len) == 0)
		_genParamSetOnOpen = (int)(atoi(v));
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		_prependParamSetsToIPic = (int)(atoi(v));
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		_startCodeEmulationPrevention = (int)(atoi(v));
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		_seqParamSetLog2MaxFrameNumMinus4 = (int)(atoi(v));
	else if (strncmp(p, "minimum intra qp", len) == 0)
		_minQPIntra = (int)(atoi(v));
	else if (strncmp(p, "minimum inter qp", len) == 0)
		_minQPInter = (int)(atoi(v));
	else if (strncmp(p, "max distortion", len) == 0)
		_dMax = (int)(atoi(v));
	else if (strncmp(p, "num rate control frames", len) == 0)
		_numRateCntlFrames = (int)(atoi(v));
	else if (strncmp(p, "max bits per frame", len) == 0)
		_maxBitsPerFrame = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		_iPictureDMaxMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		_iPictureDMaxFraction = (int)(atoi(v));
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		_rateOvershootPercent = (int)(atoi(v));
  else if (strncmp(p, "enable roi encoding", len) == 0)
    _enableROIEncoding = (int)(atoi(v));
  else
	{
		_errorStr = "[H264v2Codec::SetParameter] Write parameter not supported";
		return(0);
	}//end else...

	return(1);
}//end SetParameter.

/**
-----------------------------------------------------------------------
  Member interface functions.
-----------------------------------------------------------------------
*/
void* H264v2Codec::GetMember(const char* type, int* length)
{
	char*	p = (char *)type;
	int		len = (int)strlen(p);
	void* pRet = NULL;
	*length = 0;

	if (strncmp(p, "macroblocks", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_pMb;
	}
	else if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_autoIFrameIncluded;
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    *length = _mbLength;
    pRet = (void *)_roiMultiplier;
  }
  else if (strncmp(p, "reference", len) == 0)
	{
		*length = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		pRet = (void *)_pRLum;
	}
	else if (strncmp(p, "currseqparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_seqParam[_currSeqParam]));
	}
	else if (strncmp(p, "currpicparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_picParam[_currPicParam]));
	}
	else if (strncmp(p, "members", len) == 0)
	{
		int numMembers = (int)MEMBER_LEN;
		*length = 1;
		pRet = (void *)(numMembers);	///< Note that MEMBER_LEN is converted to a pointer type.
	}//end else if members...
	else
		_errorStr = "[H264v2Codec::GetMember] Read member not supported";

	return(pRet);
}//end GetMember.

void H264v2Codec::GetMemberName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= MEMBER_LEN))
		return;
	*name = (const char *)MEMBER_LIST[ordinal];
	*length = (int)strlen(MEMBER_LIST[ordinal]);

}//end GetMemberName.

int H264v2Codec::SetMember(const char* type, void* pValue)
{
	int	 i;
	char *p = (char *)type;
	int  len = (int)strlen(p);

	if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
    if (_autoIFrameIncluded == NULL) return(1);  ///< Do nothing.

    bool* pV = (bool *)pValue;
		for (i = 0; i < _mbLength; i++)
			_autoIFrameIncluded[i] = pV[i];
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    if (_roiMultiplier == NULL)
    {
      _errorStr = "[H264v2Codec::SetMember] Region of interest array not active";
      return(0);
    }//end !_roiMultiplier...

    double* pV = (double *)pValue;
    for (i = 0; i < _mbLength; i++)
      _roiMultiplier[i] = pV[i];
  }
  else
	{
		_errorStr = "[H264v2Codec::SetMember] Write member not supported";
		return(0);
	}//end else...

	return(1);
}//end SetMember.

/**
-----------------------------------------------------------------------
  Public Implementation.
-----------------------------------------------------------------------
*/
/** Open the codec for encoding/decoding.
The state of the codec and memory allocations are made in this method and are
entirely dependent on the codec parameters. Using SetParameter() all parmeters
must be set prior to calling this methods.
@return : 1 = success, 0 = failure.
*/
int H264v2Codec::Open(void)
{
	int i;

	/// If already open then close first before continuing.
	if (_codecIsOpen)
		Close();

	/// --------------- Configure Sequence & Picture parameter sets -----------------
	/// The _genParamSetOnOpen parameter determines whether or not the seq/pic params 
	/// are generated and set in this call to Open(). If the param sets are to be generated 
	/// then the SetParameters() method calls must have set the appropriate codec params 
	/// prior to calling Open()as these settings are dependent on the codec parameters.
	/// If the param sets are not to be generated then the codec params must be extracted
	/// from the seq/pic param sets.
	if (_genParamSetOnOpen)
	{
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set sequence parameter set";
			Close();
			return(0);
		}//end if !SetSeqParamSet...

		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set picture parameter set";
			Close();
			return(0);
		}//end if !SetPicParamSet...
	}//end if _genParamSetOnOpen...
	else
	{
		if (!GetCodecParams(_currPicParam))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !GetCodecParams...
	}//end else...

	/// --------------- Create encoded SPS and PPS streams ----------------------------------------
  /// Every I-Pic will have an SPS NAL, PPS NAL and an IDR NAL concatenated together in a single 
  /// stream. Create a cached param set for the current selection to use in the Code() method.
	if (_prependParamSetsToIPic)
	{
		int tempPicCodingType = _pictureCodingType;

		_pictureCodingType = H264V2_SEQ_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncSeqParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encSeqParamByteLen = GetCompressedByteLength();

		_pictureCodingType = H264V2_PIC_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncPicParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encPicParamByteLen = GetCompressedByteLength();

		/// Restore state.
		_pictureCodingType = tempPicCodingType;

	}//end if _prependParamSetsToIPic...

	  /// --------------- Alloc image memory ----------------------------------------------
	/// Create an image memory space.
	_lumWidth = _width;
	_lumHeight = _height;
	_chrWidth = _width / 2;
	_chrHeight = _height / 2;

	/// Alloc a large contiguous block with Lum first followed by ChrU then ChrV
	/// for both image blocks of input and reference.
	int lumSize = _lumWidth * _lumHeight;
	int chrSize = _chrWidth * _chrHeight;
	int imgSize = lumSize + 2 * chrSize;
	/// In/Out and ref images with primary lum at the head.
	_pLum = new short[2 * imgSize];
	if (!_pLum)
	{
		_errorStr = "[H264Codec::Open] Image memory unavailable";
		Close();
		return(0);
	}//end if !_pLum...
	  /// Place each image and colour component head pointer.
	_pChrU = &(_pLum[lumSize]);												///< End of _pLum.
	_pChrV = &(_pLum[lumSize + chrSize]);							///< End of _pChrU.
	_pRLum = &(_pLum[imgSize]);												///< End of input image.
	_pRChrU = &(_pLum[imgSize + lumSize]);							///< End of image and _pRLum.
	_pRChrV = &(_pLum[imgSize + lumSize + chrSize]);		///< End of _pRChrU.

  /// Zero the reference and the previous input image spaces. Note that the mem
	/// is contiguous.
	memset((void *)_pLum, 0, 2 * imgSize * sizeof(short));

	/// --------------- Configure the overlays to the img mem -------------------------
	/// The encoding/decoding of the residual image is performed on 4x4 blocks within
	/// each macroblock of the in/out and ref images.
	_Lum = new OverlayMem2Dv2(_pLum, _lumWidth, _lumHeight, 16, 16);
	_RefLum = new OverlayMem2Dv2(_pRLum, _lumWidth, _lumHeight, 16, 16);
	_Cb = new OverlayMem2Dv2(_pChrU, _chrWidth, _chrHeight, 8, 8);
	_RefCb = new OverlayMem2Dv2(_pRChrU, _chrWidth, _chrHeight, 8, 8);
	_Cr = new OverlayMem2Dv2(_pChrV, _chrWidth, _chrHeight, 8, 8);
	_RefCr = new OverlayMem2Dv2(_pRChrV, _chrWidth, _chrHeight, 8, 8);
	if ((_Lum == NULL) || (_RefLum == NULL) || (_Cb == NULL) ||
		(_RefCb == NULL) || (_Cr == NULL) || (_RefCr == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image and reference overlay objects";
		Close();
		return(0);
	}//end if !_Lum...

	  /// --------------- Alloc and configure prediction mem data objects ---------------------
	_p16x16 = new short[256];	///< 16x16 block for predicition operations.
	_16x16 = new OverlayMem2Dv2(_p16x16, 16, 16, 16, 16);
	_p8x8_0 = new short[64];	///< 8x8 blocks for predicition operations.
	_8x8_0 = new OverlayMem2Dv2(_p8x8_0, 8, 8, 8, 8);
	_p8x8_1 = new short[64];
	_8x8_1 = new OverlayMem2Dv2(_p8x8_1, 8, 8, 8, 8);

	if ((_p16x16 == NULL) || (_16x16 == NULL) ||
		(_p8x8_0 == NULL) || (_8x8_0 == NULL) ||
		(_p8x8_1 == NULL) || (_8x8_1 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot create prediction memory objects";
		Close();
		return(0);
	}//end if !_p16x16...

	/// ---------------- Configure Macroblock cache objects -----------------------------
	_mbImg = new H264MbImgCache();
	if (_mbImg == NULL)
	{
		_errorStr = "[H264Codec::Open] Cannot create macroblock image cache object";
		Close();
		return(0);
	}//end if !_mbImg...
	_mbImg->Create();

	/// --------------- Configure Macroblock data objects -----------------------------
	int mbWidth = _lumWidth / 16;		///< Note: Assuming mod 16 image dimensions (potential problem).
	int mbHeight = _lumHeight / 16;
	_mbLength = mbWidth * mbHeight;

	_pMb = new MacroBlockH264[_mbLength];
	_Mb = new MacroBlockH264*[mbHeight];	///< Address array.

	/// Only specified macroblocks are included in the detection of an I-frame. This
	/// flag list is used to indicate that inclusion.
	_autoIFrameIncluded = new bool[_mbLength];

	if ((_pMb == NULL) || (_Mb == NULL) || (_autoIFrameIncluded == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate macroblock data objects";
		Close();
		return(0);
	}//end if !_pMB...

	for (i = 0; i < mbHeight; i++)	///< Load the address array.
		_Mb[i] = &(_pMb[i * mbWidth]);

	/// Load the macroblock image mem 2-D offsets, indices and neighbourhood variables. There
	/// is only one slice (slice num = 0) and therefore extends from macroblock index 0..._mbLength-1.
	MacroBlockH264::Initialise(mbHeight, mbWidth, 0, _mbLength - 1, 0, _Mb);

	/// Load the flag for each macroblock that includes/excludes it from the 
	/// auto I-frame test during motion estimation. Default to include all.
	for (i = 0; i < _mbLength; i++)
		_autoIFrameIncluded[i] = 1;

	/// --------------- Configure colour converters ---------------------------------
	if (_inColour == H264V2_RGB24)
	{
		/// Encoder input.
#ifdef _CCIR601
		_pInColourConverter = new ConvRGB24toYUV420CCIR601V16Real(_width, _height);
#else
		_pInColourConverter = new ConvRGB24toYUV420v16FixP(_width, _height);
#endif

		if (_pInColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate input colour converter";
			Close();
			return(0);
		}//end if !_pInColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pInColourConverter->SetFlip(_flip);
	}//end if _inColour...

	if (_outColour == H264V2_RGB24)
	{
		/// Decoder output.
#ifdef _CCIR601
			_pOutColourConverter = new RealYUV420toRGB24CCIR601ConverterVer16(_width, _height);
#else
			_pOutColourConverter = new ConvYUV420_16toBGR24(_width, _height);	//, 128
#endif

		if (_pOutColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate output colour converter";
			Close();
			return(0);
		}//end if !_pOutColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pOutColourConverter->SetFlip(_flip);

	}//end if _outColour...

	  /// --------------- Instantiate IT filters ------------------------------------
	  /// Create Integer Transformers (IT) and their inverses for AC and DC coeffs. The
	  /// quantisers are included in the IT transform classes.
	_pF4x4TLum = new FastForward4x4ITImpl2();
	_pF4x4TChr = new FastForward4x4ITImpl2();
	_pFDC4x4T = new FastForwardDC4x4ITImpl1();
	_pFDC2x2T = new FastForwardDC2x2ITImpl1();
	_pI4x4TLum = new FastInverse4x4ITImpl1();
	_pI4x4TChr = new FastInverse4x4ITImpl1();
	_pIDC4x4T = new FastInverseDC4x4ITImpl1();
	_pIDC2x2T = new FastInverseDC2x2ITImpl1();

	if ((_pF4x4TLum == NULL) || (_pF4x4TChr == NULL) || (_pFDC4x4T == NULL) || (_pFDC2x2T == NULL) ||
		(_pI4x4TLum == NULL) || (_pI4x4TChr == NULL) || (_pIDC4x4T == NULL) || (_pIDC2x2T == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Integer Transform filter objects";
		Close();
		return(0);
	}//end if !_pF4x4TLum...

	  /// Set default modes and added scaling for IT filters.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	_pFDC2x2T->SetMode(IForwardTransform::TransformAndQuant);
	_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
	_pIDC4x4T->SetMode(IInverseTransform::TransformAndQuant);
	_pIDC2x2T->SetMode(IInverseTransform::TransformAndQuant);

	// --------------- Create the Vlc encoders and decoders --------------------------
	/// Create the vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = new PrefixH264VlcEncoderImpl1();
	_pPrefixVlcDec = new PrefixH264VlcDecoderImpl1();
	_pCoeffTokenVlcEnc = new CoeffTokenH264VlcEncoder();
	_pCoeffTokenVlcDec = new CoeffTokenH264VlcDecoder();
	_pTotalZeros4x4VlcEnc = new TotalZeros4x4H264VlcEncoder();
	_pTotalZeros4x4VlcDec = new TotalZeros4x4H264VlcDecoder();
	_pTotalZeros2x2VlcEnc = new TotalZeros2x2H264VlcEncoder();
	_pTotalZeros2x2VlcDec = new TotalZeros2x2H264VlcDecoder();
	_pRunBeforeVlcEnc = new RunBeforeH264VlcEncoder();
	_pRunBeforeVlcDec = new RunBeforeH264VlcDecoder();

	/// Vlc encoder and decoder for the coded block pattern.
	_pBlkPattVlcEnc = new CodedBlkPatternH264VlcEncoder();
	_pBlkPattVlcDec = new CodedBlkPatternH264VlcDecoder();

	/// Vlc encoder and decoder for the delta QP.
	_pDeltaQPVlcEnc = new ExpGolombSignedVlcEncoder();
	_pDeltaQPVlcDec = new ExpGolombSignedVlcDecoder();

	/// Vlc encoder and decoder for the macroblock type.
	_pMbTypeVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pMbTypeVlcDec = new ExpGolombUnsignedVlcDecoder();

	/// Vlc encoder and decoder for intra chr pred mode. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbIChrPredModeVlcEnc = _pMbTypeVlcEnc;
	_pMbIChrPredModeVlcDec = _pMbTypeVlcDec;

	/// Vlc encoder and decoder for motion vector differences. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbMotionVecDiffVlcEnc = _pDeltaQPVlcEnc;
	_pMbMotionVecDiffVlcDec = _pDeltaQPVlcDec;

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = _pMbTypeVlcEnc;
	_pHeaderUnsignedVlcDec = _pMbTypeVlcDec;
	_pHeaderSignedVlcEnc = _pDeltaQPVlcEnc;
	_pHeaderSignedVlcDec = _pDeltaQPVlcDec;

	if ((_pPrefixVlcEnc == NULL) || (_pPrefixVlcDec == NULL) ||
		(_pCoeffTokenVlcEnc == NULL) || (_pCoeffTokenVlcDec == NULL) ||
		(_pTotalZeros4x4VlcEnc == NULL) || (_pTotalZeros4x4VlcDec == NULL) ||
		(_pTotalZeros2x2VlcEnc == NULL) || (_pTotalZeros2x2VlcDec == NULL) ||
		(_pRunBeforeVlcEnc == NULL) || (_pRunBeforeVlcDec == NULL) ||
		(_pBlkPattVlcEnc == NULL) || (_pBlkPattVlcDec == NULL) ||
		(_pDeltaQPVlcEnc == NULL) || (_pDeltaQPVlcDec == NULL) ||
		(_pMbTypeVlcEnc == NULL) || (_pMbTypeVlcDec == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Vlc codec objects";
		Close();
		return(0);
	}//end if !_pPrefixVlcEnc...

	  /// Create a CAVLC encoder and decoder for each coeff block size.
	_pCAVLC4x4 = new CAVLCH264Impl();
	_pCAVLC2x2 = new CAVLCH264Impl();
	if ((_pCAVLC4x4 == NULL) || (_pCAVLC2x2 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate CAVLC codec objects";
		Close();
		return(0);
	}//end if !_pCAVLC4x4...

	  /// Attach the vlc encoders and decoders to the associated CAVLC.
	_pCAVLC4x4->SetMode(CAVLCH264Impl::Mode4x4);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcEncoder(_pTotalZeros4x4VlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcDecoder(_pTotalZeros4x4VlcDec);

	_pCAVLC2x2->SetMode(CAVLCH264Impl::Mode2x2);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcEncoder(_pTotalZeros2x2VlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcDecoder(_pTotalZeros2x2VlcDec);

	// --------------- Configure bit stream access -----------------------------------
	_pBitStreamWriter = new BitStreamWriterMSB();
	_pBitStreamReader = new H264BitStreamReader();
	if ((_pBitStreamWriter == NULL) || (_pBitStreamReader == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate bit stream access objects";
		Close();
		return(0);
	}//end if !_pBitStreamWriter...

	  /// --------------- Configure motion estimators -----------------------------------

	/// Create a motion vector predictor for the motion estimator to use in biasing towards
	/// the predicted vector when distortion choise is ambiguous.
	_pMotionPredictor = new H264MotionVectorPredictorImpl1(_pMb);
	if (!_pMotionPredictor)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector predictor object";
		Close();
		return(0);
	}//end if !_pMotionPredictor...

	  /// Select an appropriate motion estimator.
	int motionVectorRange;	///< In 1/4 pel units but also required for motion compensator in full pel units.
	if ((_width <= 1408) && (_height <= 1152))
		motionVectorRange = 512;	///< [-128.00 ... 127.75]
	else
		motionVectorRange = 1024;	///< [-256.00 ... 255.75]

	/// Fast less accurate estimator.
	//_pMotionEstimator = new MotionEstimatorH264ImplMultiresCrossVer2( (const void *)_pLum,	///< Multi res estimation.
	//	                                                                (const void *)_pRLum,
	//	                                                                _lumWidth,
	//	                                                                _lumHeight,
	//	                                                                motionVectorRange, ///< In 1/4 pel units.
	//	                                                                _pMotionPredictor,
	//	                                                                _autoIFrameIncluded);

	//	_pMotionEstimator = new MotionEstimatorH264ImplMultiresCross(	(const void *)_pLum,	///< Multi res estimation.
	//																																(const void *)_pRLum,
	//																																_lumWidth,
	//																																_lumHeight,
	//																																motionVectorRange, ///< In 1/4 pel units.
	//																																_autoIFrameIncluded);

  /// Cross search algorithm with partial sums as defined in the std reference implementations of H264
  _pMotionEstimator = new MotionEstimatorH264ImplCross( (const void *)_pLum,
                                                        (const void *)_pRLum,
                                                        _lumWidth,
                                                        _lumHeight,
                                                        motionVectorRange, ///< In 1/4 pel units.
                                                        _pMotionPredictor,
                                                        _autoIFrameIncluded);

  /// Slow more accurate multiresolution estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplMultires((const void *)_pLum,	///< Multi res estimation.
	//																													(const void *)_pRLum,
	//																													_lumWidth,
	//																													_lumHeight,
	//																													motionVectorRange, ///< In 1/4 pel units
	//																													_autoIFrameIncluded);

		/// Slowest full accurate estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplFull(	(const void *)_pLum,
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

		/// Test motion estimator for collecting data. Full pel only full search based estimation.
	//	_pMotionEstimator = new MotionEstimatorH264ImplTest(	(const void *)_pLum,	///< Multi res estimation.
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

	if (_pMotionEstimator != NULL)
	{
		/// Implementation specific modes.
		_pMotionEstimator->SetMode(0);	///< Auto mode.

		//_motionFactor = 2;	///< Abs diff algorithm.
		_motionFactor = 4;	///< Sqr err algorithm.

		if (!_pMotionEstimator->Create())
		{
			_errorStr = "[H264Codec::Open] Cannot create motion estimator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionEstimator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion estimator object";
		Close();
		return(0);
	}//end if else...

	  /// --------------- Configure motion compensator -----------------------------------
	  /// The motion compensator requires the range param to be in full pel units.	
	_pMotionCompensator = new MotionCompensatorH264ImplStd(motionVectorRange / 4);

	if (_pMotionCompensator != NULL)
	{
		if (!_pMotionCompensator->Create((void *)_pRLum, _lumWidth, _lumHeight, 16, 16))
		{
			_errorStr = "[H264Codec::Open] Cannot create motion compensator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionCompensator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion compensator object";
		Close();
		return(0);
	}//end if else...

	  /// Create a motion vector list to hold the decoded vectors for the compensation process.
	_pMotionVectors = new VectorStructList(VectorStructList::SIMPLE2D);
	if (!_pMotionVectors)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector list object";
		Close();
		return(0);
	}//end if !_pMotionVectors...
	if (!_pMotionVectors->SetLength(mbWidth * mbHeight)) ///< One per Mb for 16x16 vectors only.
	{
		_errorStr = "[H264Codec::Open] Insufficient mem for motion vector list";
		Close();
		return(0);
	}//end if !SetLength...

	  /// --------------- Create image plane encoders and decoders ----------------------
	  /// Select an Intra Decoder.
	_pIntraImgPlaneDecoder = new IntraImgPlaneDecoderImplStdVer1(this);
	/// Set the Inter decoder.
	_pInterImgPlaneDecoder = new InterImgPlaneDecoderImplStdVer1(this);

	/// Select an Intra and Inter Encoder depending on the mode.
	if (_modeOfOperation == H264V2_OPEN)
	{
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplStdVer1(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplStdVer1(this);
	}//end if _modeOfOperation...
	else if (_modeOfOperation == H264V2_MB_QP_MINMAX_ADAPTIVE)
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplMinMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplMinMax(this);
	}//end else...
	else	///< if((_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)||(_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE))
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplDMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplDMax(this);

		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			switch (_rateControlModelType)
			{
			case H264V2_RATE_CONTROL_MODEL_QUAD:
				_pRateCntlIFrames = new RateControlImplQuad(40.0, 20000.0);
				_pRateCntlPFrames = new RateControlImplQuad(40.0, 20000.0);
				break;
			case H264V2_RATE_CONTROL_MODEL_POW:
				_pRateCntlIFrames = new RateControlImplPow(65.0, -0.9);
				_pRateCntlPFrames = new RateControlImplPow(15000.0, -1.3);
				break;
			case H264V2_RATE_CONTROL_MODEL_LOG:
				_pRateCntlIFrames = new RateControlImplLog(0.1, 1.2);
				_pRateCntlPFrames = new RateControlImplLog(0.2, 1.4);
				break;
      /*
			case H264V2_RATE_CONTROL_MODEL_MULTI:
			  {
				  double modelParam[RateControlImplMultiModel::MODELS][2];  ///< Initial a and b model parameter per model.
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 65.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -0.9;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.1;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.2;
				  _pRateCntlIFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 15000.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -1.3;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.2;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.4;
				  _pRateCntlPFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
			  }
			break;
      */
			}//end switch _rateControlModelType...

			if ((_pRateCntlPFrames != NULL) && (_pRateCntlIFrames != NULL))
			{
				if ((!_pRateCntlPFrames->Create(_numRateCntlFrames)) || (!_pRateCntlIFrames->Create(_numRateCntlFrames)))
				{
					_errorStr = "[H264Codec::Open] Cannot create rate controllers";
					Close();
					return(0);
				}//end if !Create...
				switch (_rateControlModelType)
				{
				case H264V2_RATE_CONTROL_MODEL_QUAD:
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);  ///< Quad Abs Diff limits.
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);
					break;
				case H264V2_RATE_CONTROL_MODEL_POW:
				case H264V2_RATE_CONTROL_MODEL_LOG:
				/*case H264V2_RATE_CONTROL_MODEL_MULTI:*/
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);  ///< Multi-model Sqr Diff limits
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);
					break;
				}//end switch _rateControlModelType...
			}//end if _pRateCntlPFrames...
			else
			{
				_errorStr = "[H264Codec::Open] Cannot instantiate rate controllers";
				Close();
				return(0);
			}//end else...
		}//end if _modeOfOperation...
	}//end else...

	if ((_pIntraImgPlaneEncoder == NULL) || (_pIntraImgPlaneDecoder == NULL) ||
		(_pInterImgPlaneEncoder == NULL) || (_pInterImgPlaneDecoder == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image plane encoder and decoder objects";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...
	if ((!_pIntraImgPlaneEncoder->Create(_mbLength)) ||
		(!_pInterImgPlaneEncoder->Create(_mbLength)))
	{
		_errorStr = "[H264Codec::Open] Cannot create image plane encoders";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...

   /// --------------- Create Region of Interest members ----------------------
  _roiMultiplier = new double[_mbLength];
  if(_roiMultiplier == NULL)
  {
    _errorStr = "[H264Codec::Open] Cannot create region of interest members";
    Close();
    return(0);
  }//end if !_roiMultiplier...

   /// Fill it with 1.0 to have no effect on the distortion.
  for (i = 0; i < _mbLength; i++)
    _roiMultiplier[i] = 1.0;

  /// ---------------- Start at the beginning ----------------------------------
	_lastPicCodingType = H264V2_INTRA;
	_prevMotionDistortion = -1;
	_maxFrameNum = 1 << (_seqParam[_currSeqParam]._log2_max_frame_num_minus4 + 4);	///< Max limit (modulus) for _frameNum.
	_idrFrameNum = 0;	///< The starting I-frame counter that must then be different for every contiguous I-frame.
	Restart();

	/// Set up the optimisation time limit timer. If it does not exist then force the parameter to zero.
	if (!SetCounter())
		_timeLimitMs = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/*
	  BlockH264* pB1 = new BlockH264(4, 4);
	  BlockH264* pB2 = new BlockH264(4, 4);
	  short* pB1Mem = pB1->GetBlk();

	  /// Fill with random numbers between -250..250.
	//  srand( 34594938 );
	  srand( 2439967 );
	  for (i = 0; i < 16; i++ )
	  {
		int u = (double)rand() / (RAND_MAX + 1) * (250 - (-250))
			  + (-250);
		pB1Mem[i] = short(u);
	  }//end for i...
	  pB2->CopyBlock(pB1);  ///< Hold a copy to compare with.
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/InputBlk.csv", "Input Blk");

	  /// Forward DCT QP=1
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	  _pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTBlk.csv", "DCT Blk");
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP1Blk.csv", "DCT QP1 Blk");

	  /// Inverse DCT QP=1
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 1);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP1Blk.csv", "IQP1 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP1Blk.csv", "Output QP1 Blk");

	  /// Reload input.
	  pB1->CopyBlock(pB2);
	  /// Forward DCT QP=40
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 40);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP40Blk.csv", "DCT QP40 Blk");

	  /// Inverse DCT QP=40
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 40);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP40Blk.csv", "IQP40 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP40Blk.csv", "Output QP40 Blk");

	  delete pB2;
	  delete pB1;
	*/
	////////////////////////////////////////////////////////////////////////////////////////////////////

	_errorStr = "[H264Codec::Open] No Erorr";
	_codecIsOpen = 1;
	return(1);
}//end Open.

/** Encode one frame of pels to a compressed stream.
The input source pels in the format specified by "incolour" parameter are compressed
to the output stream. The codeParameter specifies either the max size in bits of the
pCmp buffer or the number of bits to target during the compression process. The interpretation
is determined by the "mode of operation" parameter. For SPS and PPS encoding the input
pSrc is ignored.
@param  pSrc          : Input raw pels of one complete frame.
@param  pCmp          : Output compressed stream buffer.
@param  codeParameter : Mode of operation based bit size limits.
@return               : 1 = success, 0 = failure.
*/
int	H264v2Codec::Code(void* pSrc, void* pCmp, int codeParameter)
{
	int allowedBits, bitsUsed;

	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
		return(CodeNonPicNALTypes(pCmp, codeParameter));

	if (!_codecIsOpen)
	{
		_errorStr = "[H264V2Codec::Code] Codec is not open";
		return(0);
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Code] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Mark the start time of the encoding process.
	if (_timeLimitMs)
		_startTime = (int)GetCounter();
#ifdef H264V2_DUMP_TIMING
	_startTime = (int)GetCounter();
#endif

	/// Interpret the code parameter as a frame bit limit or avg bit rate.
	int frameBitLimit = codeParameter;
	_avgBitsPerFrame = codeParameter;
	double avgBppRate = (double)(_avgBitsPerFrame) / (double)(_lumWidth*_lumHeight);  ///< Bit rate in bits per pel.
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		frameBitLimit = _maxBitsPerFrame; ///< Bit limit must be made sufficiently large for variations in the buffered rate per frame.

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	_bitStreamSize = 0;

	/// Reset the stream writer with the frame bit limit. 
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Only IDR and P pictures are supported.
	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
	{
		_errorStr = "[H264v2Codec::Code] Picture coding type not supported";
		return(0);
	}//end if !H264V2_INTRA...

   ///-------------- Colour Space Conversion -----------------------------------------------
  if (_inColour == H264V2_YUV420P16)	      ///< The natural colour space of the encoder with type = short.
		memcpy((void *)_pLum, (const void *)pSrc, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_inColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			_pLum[i] = (short)((unsigned char *)pSrc)[i];
	}//end if H264V2_YUV420P8...
	else
		_pInColourConverter->Convert((void *)pSrc, (void *)_pLum, (void *)_pChrU, (void *)_pChrV);

  ///-------------- Motion Estimation -----------------------------------------------
  /// Motion estimation is used to determine if an IDR frame should be inserted.
	if (_pictureCodingType == H264V2_INTER)
	{
		/// Motion estimation.
		long motionDistortion = 0;

		/// The estimator implementation was chosen in Open() depending on the mode selected.
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			/// Motion vector lambda adaptation in this mode uses a TCP-like algorithm. Note that it uses the most recent past
      /// P-frame rate control results applied to this P-frame.
			double deltaLambda = 0.0;
			if (_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->UpperDistortionOverflow())
				deltaLambda = MVLAMBDA_MULT*(MVLAMBDA_MAX - _mvLambda);
			else if ((_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->LowerDistortionOverflow()) || (_mvLambda > MVLAMBDA_STEADYSTATE))
				deltaLambda = MVLAMBDA_STEP;
			_mvLambda += deltaLambda;
			if (_mvLambda < 0.0) _mvLambda = 0.0;

			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion, (void *)(&_mvLambda)));
		}//end if H264V2_MB_QP_AVG_ADAPTIVE...
		else
			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion));

		/// The estimation results are processed into an encoded structure list. A 
		/// decision is made on the type of encoding as predictive or basic and 
		/// returns the selection. The _Motion member reflects the choice.

		/// Auto I-picture detection.
		if (_autoIPicture && (_prevMotionDistortion != -1)) ///< Previous frame was not an I-Picture.
		{
			/// Test for an I-picture.
			if (motionDistortion > (_motionFactor * _prevMotionDistortion))
				_pictureCodingType = H264V2_INTRA;
		}///end if _prevMotionDistortion...

		_prevMotionDistortion = motionDistortion;

		/// Force an I-picture if frame counter has wraped around in the modulus calculation.
		if (_frameNum == 0)
			_pictureCodingType = H264V2_INTRA;

	}//end if H264V2_INTER...

	/// The motion estimation process is used to determine if this picture
	/// should rather be coded as an IDR picture. Therefore the INTRA 
	/// picture type coding is done afterwards. 

  ///-------------- Pre-encoding rate control ---------------------------------
  if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
  {
    /// Reset global frame accumulator.
    _frameMSD = 0;
    _frameMAD = 0;
    _frameMAD_N = 0;
    _predFrmMAD = 0.0;

    if (_pictureCodingType == H264V2_INTER)
    {
      /// Distortion is modified only when there is valid data in the rate control model. 
      /// Otherwise it remains at the previous frame's settings.
      if (_pRateCntlPFrames->ValidData())
      {
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlPFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      if (_pRateCntlIFrames->ValidData())
      {
        /// Readjust average frame bits with multiplier.fraction factor.
        avgBppRate = (avgBppRate * (double)_iPictureMultiplier) + ((avgBppRate * (double)_iPictureFraction) / 10.0);
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlIFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end else if H264V2_INTRA...
  }//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Headers and Preparation  ---------------------------------
  /// For INTRA pictures and before any encoding begins readjust the 
	/// allowable bits based on the I-picture multiplier parameters.
	if (_pictureCodingType == H264V2_INTRA)
	{
		/// Continuously divide by 10 until in the range 0..9.
		while (_iPictureFraction > 10)
			_iPictureFraction = (_iPictureFraction / 10);
		/// Readjust frame bits with multiplier.fraction factor. Protect against excessively large bit limits that result in integer wrapping.
		int prior = frameBitLimit;
		frameBitLimit = (frameBitLimit * _iPictureMultiplier) + ((frameBitLimit * _iPictureFraction) / 10);
		if (frameBitLimit < prior) frameBitLimit = prior;
		_pBitStreamWriter->SetStreamBitSize(frameBitLimit);
		/// New bit limit setting.
		bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	  /// Reset the frame number for I-pics.
		_frameNum = 0;

		/// Prepend SPS and PPS to the I-picture.
		if (_prependParamSetsToIPic)
		{
			allowedBits = bitLimit - _bitStreamSize;
			int paramTotBitLen = 8 * (_encSeqParamByteLen + _encPicParamByteLen);
			if (allowedBits < paramTotBitLen)
			{
				_errorStr = "[H264V2Codec::Code] Cannot prepend SPS and PPS to I-Picture stream";
				return(0);
			}//end if allowedBits...

			/// Write the pre-encoded SPS to the stream.
			int i;
			for (i = 0; i < _encSeqParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncSeqParam[i]);

			/// Write the pre-encoded PPS to the stream.
			for (i = 0; i < _encPicParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncPicParam[i]);

			_bitStreamSize += paramTotBitLen;

		}//end if _prependParamSetsToIPic...
	}//end if H264V2_INTRA...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::Code] Cannot write start code to stream";
		return(0);
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Define the NAL unit header based on the seleceted picture coding type. The final NAL type
	/// is only known at this point in the process.
	if (_pictureCodingType == H264V2_INTER)
	{
		_nal._ref_idc = 2;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::NonIDR_NoPartition_Slice;
	}//end if H264V2_INTER...
	else	///< if(_pictureCodingType == H264V2_INTRA)
	{
		_nal._ref_idc = 3;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::IDR_Slice;
	}//end else...

	  /// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice header layer with its header flags to
	/// the stream. There is only one slice so the header, macroblocks (slice
	/// data) and tail may be coded in a linear order.
	_slice._frame_num = _frameNum;
	_slice._idr_pic_id = _idrFrameNum;
	/// Force the image plane encoders to use _pQuant as the slice qp and therefore the
	/// slice header is determined before encoding and may be added to the bit stream here.
	_slice._qp = _pQuant;
	_slice._qp_delta = _slice._qp - (_picParam[_currPicParam]._pic_init_qp_minus26 + 26);
	_slice._pic_parameter_set_id = _currPicParam;
	/// Baseline profile only has two slice types and in this implementation they are
	/// used for the entire frame/picture.
	if (_pictureCodingType == H264V2_INTER)
		_slice._type = SliceHeaderH264::P_Slice_All;
	else
		_slice._type = SliceHeaderH264::I_Slice_All;

	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteSliceLayerHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Encode the entire picture. The plane encoders do not write to the stream
	/// but do require to know the available bits. Allowance is made for the single
	/// trailing bit.
	allowedBits = bitLimit - _bitStreamSize - 1;

	///-------------- Encoding process ---------------------------------
	if (_pictureCodingType == H264V2_INTRA)
	{
		_prevMotionDistortion = -1;
		Restart(); ///< Reset the loop for I-picture.

			/// The encoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of slices and their macroblocks.
		if (!_pIntraImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 1))
			return(0);	///< An error has occured.
	}//end if H264V2_INTRA...
	else if (_pictureCodingType == H264V2_INTER)
	{
		/// The encoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 3))
			return(0);	///< An error has occured.
	}//end else H264V2_INTER...

  ///-------------- Write to stream ---------------------------------
	/// Write (concatinate) the macroblock layer (slice data) with its header 
	/// flags to the stream.
	runOutOfBits = WriteSliceDataLayer(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice trailing bits to the stream. This is a min
  /// of 1 bit + zero bits to the end of the byte boundary.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Prevent start code emulation within the coded bit stream. The extra byte added
	/// to prevent the emulation is not counted as part of the bit written.
	if (_startCodeEmulationPrevention)
	{
		int offset = 0;
		if ((_pictureCodingType == H264V2_INTRA) && (_prependParamSetsToIPic))
			offset = _encSeqParamByteLen + _encPicParamByteLen;

		_bitStreamSize += InsertEmulationPrevention(_pBitStreamWriter, offset);
	}//end if _startCodeEmulationPrevention...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	///-------------- Post-encoding rate control ---------------------------------
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
	{
		/// Measured mean abs and squared difference. Members were set per mb in the ProcessInterMbImplStd() method.
		double frmMAD = (double)(_frameMAD);
		double frmMSD = (double)(_frameMSD);
		if (_frameMAD_N)
		{
			frmMAD = frmMAD / (double)(_frameMAD_N);
			frmMSD = frmMSD / (double)(_frameMAD_N);
		}//end if _frameMAD_N...

		IRateControl* lclRateCntrl = _pRateCntlPFrames; ///< Default to P-Frames.
		if (_pictureCodingType == H264V2_INTER)
		{
			/// Reset the P-Frame RDO model after I-Frames.
	    //if(_lastPicCodingType == H264V2_INTRA)
	    //  _pRateCntlPFrames->Reset();
		}//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      /// Force a rest of the mean difference buffer of P-frames to reflect the scene change.
//      _pRateCntlPFrames->Reset(0.0, 0.0, 0.0, frmMSD, frmMAD);

      /// Inform the P-frame rate controller that things will different now that their is probably a new scene sequence.
      _pRateCntlPFrames->SignalSceneChange(frmMSD, frmMAD);  
      lclRateCntrl = _pRateCntlIFrames;
    }//end else if H264V2_INTRA...

		/// Store total rate, coeff rate, distortion, mean difference (and header rate).
		double rateBpp = (double)_bitStreamSize / (double)(_lumWidth*_lumHeight);
    if(_rateControlModelType == H264V2_RATE_CONTROL_MODEL_QUAD)
		  lclRateCntrl->StoreMeasurements(rateBpp, _coeffBitsPerPel, (double)(_dMax), frmMSD, frmMAD);
    else
      lclRateCntrl->StoreMeasurements(rateBpp, rateBpp, (double)(_dMax), frmMSD, frmMAD);

	}//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Prepare for next frame ---------------------------------

	/// Any param changes required for the next picture encoding are done here.
	/// INTER pictures by default follow INTRA pictures.
	int tmpLastPicCodingType = _lastPicCodingType;
	_lastPicCodingType = _pictureCodingType;
	if (_pictureCodingType == H264V2_INTRA)
	{
		_pictureCodingType = H264V2_INTER;
		/// The IDR-frame num is by default 0 unless the previous frame was also an IDR-frame.
		/// In this case, it toggles between 1 and 0. The H.264 standard only requires
		/// consecutive IDR-frames to be different ITU-T Recommendation H.264 (03/2005) page 77.
		if ((tmpLastPicCodingType == H264V2_INTRA) && (_idrFrameNum == 0))
			_idrFrameNum = 1;
		else
			_idrFrameNum = 0;
	}//end if H264V2_INTRA...
	else
		_idrFrameNum = 0;

	///< Increment the frame number relative to the last I-frame for the next frame.
	_frameNum = (_frameNum + 1) % _maxFrameNum;

#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos < _timingTableLen)
	{
		_timingTable.WriteItem(0, _timingTablePos, _timingTablePos);
		_timingTable.WriteItem(1, _timingTablePos, (int)GetCounter() - _startTime);
		_timingTablePos++;
	}//end if _timingTablePos...
#endif

	return(1);
}//end Code.

/** Decode the compresed frame into raw pel samples.
The input types are a compressed picture IDR or P NAL unit, a SPS, a PPS or a concatenated
SPS, PPS and compressed picture. The output is the raw picture pels in the format specified
by the "outcolour" codec parameter.
@param  pCmp      : Compressed stream.
@param  bitLength : Length in bits of pCmp.
@param  pDst      : Raw pel output.
@return           : 1 = success, 0 = failure.
*/
int H264v2Codec::Decode(void* pCmp, int bitLength, void* pDst)
{
    if(!_inputFraming)
        return DecodeInternal(pCmp, bitLength, pDst, false);

    // AVC1 input: one complete sample with four-byte big-endian NAL lengths.
    // Validate the entire framing before the existing unescaper mutates payload.
    if(!pCmp || bitLength <= 0 || (bitLength & 7))
    {
        _errorStr = "[H264v2Codec::Decode] Invalid AVC1 sample length";
        return 0;
    }
    unsigned char* input = (unsigned char*)pCmp;
    const int bytes = bitLength / 8;
    int pos = 0;
    bool sawPicture = false;
    while(pos < bytes)
    {
        if(bytes - pos < 4)
        {
            _errorStr = "[H264v2Codec::Decode] Truncated AVC1 length prefix";
            return 0;
        }
        const unsigned int n = ((unsigned int)input[pos] << 24) |
            ((unsigned int)input[pos+1] << 16) |
            ((unsigned int)input[pos+2] << 8) | input[pos+3];
        pos += 4;
        if(n == 0 || n > (unsigned int)(bytes - pos))
        {
            _errorStr = "[H264v2Codec::Decode] Invalid AVC1 NAL length";
            return 0;
        }
        const unsigned int type = input[pos] & 31;
        if((input[pos] & 0x80) || sawPicture ||
           (type != 1 && type != 5 && type != 7 && type != 8))
        {
            _errorStr = "[H264v2Codec::Decode] Unsupported AVC1 NAL order or type";
            return 0;
        }
        if(type == 1 || type == 5)
            sawPicture = true;
        pos += (int)n;
    }
    if(sawPicture && (!_codecIsOpen || !pDst))
    {
        _errorStr = "[H264v2Codec::Decode] Picture requires an open codec and output buffer";
        return 0;
    }

    pos = 0;
    while(pos < bytes)
    {
        const unsigned int n = ((unsigned int)input[pos] << 24) |
            ((unsigned int)input[pos+1] << 16) |
            ((unsigned int)input[pos+2] << 8) | input[pos+3];
        pos += 4;
        if(!DecodeNAL(input + pos, (int)n, pDst))
            return 0;
        // Use the original length, not the shortened unescaped payload size.
        pos += (int)n;
    }
    return 1;
}

// Private helper. Prefix-free input starts at the NAL header, not the payload.
int H264v2Codec::DecodeNAL(void* pNal, int nalByteLength, void* pDst)
{
    return DecodeInternal(pNal, nalByteLength * 8, pDst, true);
}

int H264v2Codec::DecodeInternal(void* pCmp, int bitLength, void* pDst, bool singleNal)
{
	int	runOutOfBits = 0;
	int frameBitSize = bitLength;
	int bitsUsed = 0;
	int ret = 1;
	int moreNonPicNALUnits = 1;

	/// Set the bit stream access. The bit stream reader and related objects are instantiated within 
	/// Open() and is therefore not available for non-picture NAL types. They are temporarily created 
	/// for these other NAL types.
	_bitStreamSize = bitLength;

	if (!_codecIsOpen)		// JFO this does not work.
	{
          if(_pBitStreamReader == NULL)
	    _pBitStreamReader = new H264BitStreamReader();
          if(_pHeaderUnsignedVlcDec == NULL)
	    _pHeaderUnsignedVlcDec = new ExpGolombUnsignedVlcDecoder();
           if(_pHeaderSignedVlcDec == NULL)
	     _pHeaderSignedVlcDec = new ExpGolombSignedVlcDecoder();		
	}//end if !_codecIsOpen...

		// JFO: function cannot continue when one of 3 pointers is NULL
        if ((_pBitStreamReader == NULL) || (_pHeaderUnsignedVlcDec == NULL) || (_pHeaderSignedVlcDec == NULL))
	{
	  _errorStr = "[H264Codec::Decode] Cannot instantiate stream reader and vlc objects";
	  ret = 0;
	  goto H264V2_D_CLEAN_MEM;
	}//end if !_pBitStreamReader...


	  /// Set the stream reader.
	_pBitStreamReader->SetStream(pCmp, bitLength);
	_bitStreamSize = _pBitStreamReader->GetStreamBitSize();
	frameBitSize = _bitStreamSize;

	/// Typically in-band SPS and PPS are prepended to IDR frames. Therefore keep decoding until all
	/// non-picture NAL types are decoded. If the frameBitSize indicates at least 4 more bytes (32 bits)
	/// then we assume there is another NAL to be decoded.
	while (moreNonPicNALUnits)
	{
        if(!singleNal)
        {
		/// Extract the start code 0x00000001 from the stream.
		int startCode = _pBitStreamReader->Read(32);
		if (startCode != 1)
		{
			_errorStr = "[H264Codec::Decode] Cannot extract start code from stream";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if frameBitSize...
		frameBitSize -= 32;

        }

		/// Get the NAL header encodings off the bit stream to determine the picture coding type..
		runOutOfBits = ReadNALHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
		frameBitSize -= bitsUsed;
		if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		{
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if runOutOfBits...

		/// NAL to coding type conversion.
		switch (_nal._unit_type)
		{
		case NalHeaderH264::IDR_Slice:
			_pictureCodingType = H264V2_INTRA;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::NonIDR_NoPartition_Slice:
			/// Slice without partitioning and therefore only one set of slice parameters and NAL type = Slice type.
			_pictureCodingType = H264V2_INTER;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::SeqParamSet:
		case NalHeaderH264::PicParamSet:
		{
			int changed = 1;  ///< Indicate if the decoded params for this index have changed. Assume they have changed as the default.
			if (_nal._unit_type == NalHeaderH264::SeqParamSet)
			{
				_pictureCodingType = H264V2_SEQ_PARAM;
				/// Read the seq param set off the stream.
				runOutOfBits = ReadSeqParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currSeqParam, &changed);
			}//end if SeqParamSet...
			else ///< if(_nal._unit_type == NalHeaderH264::PicParamSet)
			{
				_pictureCodingType = H264V2_PIC_PARAM;
				/// Read the pic param set off the stream.
				runOutOfBits = ReadPicParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currPicParam, &changed);
				if (!runOutOfBits)
					_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
			}//end else...
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

			/// Read the trailing bits off the stream.
			runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

	/// If the codec is in the open state then any change in sequence or picture param set requires the
	/// codec to be restarted with these new sets. But the bit stream must be preserved and restored 
	/// after the call to Open().
			if (_codecIsOpen)
			{
				if (changed)
				{
					/// Preserve the bitstream
					IBitStreamReader* pTmpBitStreamReader = new H264BitStreamReader();
					pTmpBitStreamReader->Copy(_pBitStreamReader);

					int tmpPicCodingType = _pictureCodingType; ///< Store the coding type.

					_genParamSetOnOpen = 0; ///< Must be off if the new param sets are to be used.
					if (!Open())
					{
						delete pTmpBitStreamReader;
						ret = 0;
						goto H264V2_D_CLEAN_MEM;
					}//end if !Open...

					/// Restore the picture coding type.
					_pictureCodingType = tmpPicCodingType;
					/// Restore the bitstream.
					_pBitStreamReader->Copy(pTmpBitStreamReader);
					delete pTmpBitStreamReader;
				}//end if changed...

			}//end if _codecIsOpen...

#ifdef H264V2_DUMP_HEADERS
			if (_headerTablePos < _headerTableLen)
			{
				_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
				_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
				_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
				_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
				_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
				_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

				_headerTablePos++;
			}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

			if (singleNal || frameBitSize < 32) ///< No more units in this call.
			{
				moreNonPicNALUnits = 0;
				if (_codecIsOpen)
					return(1);
				else
				{
					/// Clean up the mem.
					ret = 1;
					goto H264V2_D_CLEAN_MEM;
				}//end else...
			}//end if frameBitSize...

		};//end SeqParamSet and PicParamSet block...
		break;
		default:
			_errorStr = "[H264v2Codec::Decode] NAL unit type not supported";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
			break;
		}//end switch _unit_type...
	}//end while moreNonPicNALUnits...

	  /// Only IDR and P pictures are decoded from here and the codec must be open.
	if (!_codecIsOpen)
	{
		_errorStr = "[H264v2Codec::Decode] Codec is not open";
		ret = 0;
		goto H264V2_D_CLEAN_MEM;
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Decode] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Remove prevention of start code emulation codes within the coded bit stream.
	if (_startCodeEmulationPrevention)
		// H264BitStreamReader omits emulation-prevention bytes without modifying input.

	/// Get the slice header encodings off the bit stream. As this implementation 
	/// has only one slice, the slice header, slice data (macroblocks) and the 
	/// slice trailing bits can be decoded in linear order.
	runOutOfBits = ReadSliceLayerHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);
	/// Load frame counter members from the decoded slice header.
	_frameNum = _slice._frame_num;
	_idrFrameNum = _slice._idr_pic_id;
	/// Load the picture and sequence parameter set references.
	_currPicParam = _slice._pic_parameter_set_id;
	_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
	/// There is only one slice so the quant parameter is picture quant + the delta slice quant.
	_slice._qp = _picParam[_currPicParam]._pic_init_qp_minus26 + 26 + _slice._qp_delta;
	_pQuant = _slice._qp;

#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos < _headerTableLen)
	{
		_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
		_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
		_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
		_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
		_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
		_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

		_headerTablePos++;
	}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

	/// Get the macroblock (slice data) encodings off the bit stream.
	runOutOfBits = ReadSliceDataLayer(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// Get the slice trailing bits off the bit stream. 
	runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// INTRA frames require the reference images to be zeroed.
	if (_pictureCodingType == H264V2_INTRA)
	{
		Restart();	///< Reset the loop and ref img.

			/// The decoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of macroblocks.
		if (!_pIntraImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end if INTRA...
	else
	{
		/// INTER picture decode.
		/// The decoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end else INTER...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	/// Convert to the output image depending on the output dimension settings. Set
	  /// up in the Open() method for the correctly selected converter.
	if (_outColour == H264V2_YUV420P16)      /// The natural colour space of the decoder with type = short.		
		memcpy((void *)pDst, (const void *)_pRLum, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_outColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			((unsigned char *)pDst)[i] = (unsigned char)_pRLum[i];
	}//end if H264V2_YUV420P8...
	else
		_pOutColourConverter->Convert(_pRLum, _pRChrU, _pRChrV, pDst);

	return(1);

	/// Clean up memory objects.
H264V2_D_CLEAN_MEM:

	// These objects are temporary only when Decode() was entered while
	// the codec was closed. When the codec is open, the header decoder
	// pointers are non-owning aliases of persistent codec objects.
    if(!_codecIsOpen)
    {        
	if(_pHeaderUnsignedVlcDec!=NULL && _pHeaderUnsignedVlcDec!=_pMbTypeVlcDec)
	{
	    delete _pHeaderUnsignedVlcDec;
	    _pHeaderUnsignedVlcDec = NULL;
	} //end if _pHeaderUnsignedVlcDec...
	if(_pHeaderSignedVlcDec!=NULL && _pHeaderSignedVlcDec!=_pDeltaQPVlcDec)
	{
	    delete _pHeaderSignedVlcDec;
	    _pHeaderSignedVlcDec = NULL;
	} //end if _pHeaderSignedVlcDec...
	if(_pBitStreamReader != NULL)
	{
	    delete _pBitStreamReader;
	    _pBitStreamReader = NULL;
	} //end if _pBitStreamReader...
    }

	return(ret);
}//end Decode.


int H264v2Codec::Close(void)
{
#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos > 0)
		_headerTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC10/CodecAnalyser/LoyisoGola_my_enc_qp48_16P.csv", ",", 1);

	_headerTablePos = 0;
#endif // H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	if (_mbRDTablePos > 1)
		_mbRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/QPvRD_Foreman.csv", ",", 1);

	_mbRDTablePos = 1;
#endif
#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos > 0)
		_timingTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/EncodeTimes.csv", ",", 1);

	_timingTablePos = 0;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
	/// Collect frame RD values.
	_frmRDTableLen = _pRateCntlPFrames->GetFameBufferLength();
	_frmRDTable.Create(4, _frmRDTableLen);  /// frame, mb Dmax, rate, MAD.

	_frmRDTable.SetHeading(0, "Frame");
	_frmRDTable.SetDataType(0, MeasurementTable::INT);
	_frmRDTable.SetHeading(1, "Dmax");
	_frmRDTable.SetDataType(1, MeasurementTable::INT);
	_frmRDTable.SetHeading(2, "Rate");
	_frmRDTable.SetDataType(2, MeasurementTable::DOUBLE);
	_frmRDTable.SetHeading(3, "MAD");
	_frmRDTable.SetDataType(3, MeasurementTable::DOUBLE);

	_frmRDTablePos = 0;

	if (_pRateCntlPFrames->ValidData())
	{
		int frmNum = _frmRDTableLen - 1; ///< Frame numbering is in reverse order.
		for (_frmRDTablePos = 0; _frmRDTablePos < _frmRDTableLen; _frmRDTablePos++, frmNum--)
		{
			_frmRDTable.WriteItem(0, _frmRDTablePos, _frmRDTablePos); ///< Frame counter.
			_frmRDTable.WriteItem(1, _frmRDTablePos, (int)(0.5 + (_pRateCntlPFrames->GetDmaxSamples())[frmNum]));
			_frmRDTable.WriteItem(2, _frmRDTablePos, (_pRateCntlPFrames->GetRateSamples())[frmNum]); ///< In bits/pixel
			_frmRDTable.WriteItem(3, _frmRDTablePos, (_pRateCntlPFrames->GetMDSamples())[frmNum]);
		}//end for _frmRDTablePos...

		_frmRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DmaxVsR_Foreman.csv", ",", 1);
		_frmRDTablePos = 0;
	}//end if ValidData...

#endif

	/// Free the image memory and associated overlays.
	_pChrU = NULL;
	_pChrV = NULL;
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;

	if(_Lum != NULL)
	    {delete _Lum; _Lum = NULL;}
	if(_Cb != NULL)
	    {delete _Cb; _Cb = NULL;}
	if(_Cr != NULL)
	    {delete _Cr; _Cr=NULL;}

	if(_RefLum != NULL)
	    {delete _RefLum; _RefLum = NULL;}
	if(_RefCb != NULL)
	    {delete _RefCb;_RefCb = NULL;}
	if(_RefCr != NULL)
	    {delete _RefCr; _RefCr = NULL;}
	if(_pLum != NULL)
	    {delete[] _pLum;_pLum = NULL;}

	if(_16x16 != NULL)
	    {delete _16x16; _16x16 = NULL;}
	if (_p16x16 != NULL)
	    {delete[] _p16x16;_p16x16 = NULL;}
	if (_8x8_0 != NULL)
	    {delete _8x8_0;_8x8_0 = NULL;}
	if (_p8x8_0 != NULL)
	    {delete[] _p8x8_0; _p8x8_0 = NULL;}
	if (_8x8_1 != NULL)
	    {delete _8x8_1; _8x8_1 = NULL;}
	if (_p8x8_1 != NULL)
	    {delete[] _p8x8_1;_p8x8_1 = NULL;}

	if (_mbImg != NULL)
	    {delete _mbImg; _mbImg = NULL;}

	/// Colour converters.
	if (_pInColourConverter != NULL)
		delete _pInColourConverter;
	_pInColourConverter = NULL;

	if (_pOutColourConverter != NULL)
		delete _pOutColourConverter;
	_pOutColourConverter = NULL;

	/// IT transform filters.
	if (_pF4x4TLum != NULL)
		delete _pF4x4TLum;
	_pF4x4TLum = NULL;
	if (_pF4x4TChr != NULL)
		delete _pF4x4TChr;
	_pF4x4TChr = NULL;
	if (_pFDC4x4T != NULL)
		delete _pFDC4x4T;
	_pFDC4x4T = NULL;
	if (_pFDC2x2T != NULL)
		delete _pFDC2x2T;
	_pFDC2x2T = NULL;
	if (_pI4x4TLum != NULL)
		delete _pI4x4TLum;
	_pI4x4TLum = NULL;
	if (_pI4x4TChr != NULL)
		delete _pI4x4TChr;
	_pI4x4TChr = NULL;
	if (_pIDC4x4T != NULL)
		delete _pIDC4x4T;
	_pIDC4x4T = NULL;
	if (_pIDC2x2T != NULL)
		delete _pIDC2x2T;
	_pIDC2x2T = NULL;

	/// Vlc codecs that were used as references and not instantiated.
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// Vlc encoders and decoders.
	if (_pPrefixVlcEnc != NULL)
	    {delete _pPrefixVlcEnc; _pPrefixVlcEnc = NULL;}
	if (_pPrefixVlcDec != NULL)
	    {delete _pPrefixVlcDec; _pPrefixVlcDec = NULL;}

	if (_pCoeffTokenVlcEnc != NULL)
	    {delete _pCoeffTokenVlcEnc; _pCoeffTokenVlcEnc = NULL;}
	if (_pCoeffTokenVlcDec != NULL)
	    {delete _pCoeffTokenVlcDec; _pCoeffTokenVlcDec = NULL;}

	if (_pTotalZeros4x4VlcEnc != NULL)
	    {delete _pTotalZeros4x4VlcEnc; _pTotalZeros4x4VlcEnc = NULL;}
	if (_pTotalZeros4x4VlcDec != NULL)
	    {delete _pTotalZeros4x4VlcDec; _pTotalZeros4x4VlcDec = NULL;}

	if (_pTotalZeros2x2VlcEnc != NULL)
	    {delete _pTotalZeros2x2VlcEnc; _pTotalZeros2x2VlcEnc = NULL;}
	if (_pTotalZeros2x2VlcDec != NULL)
	    {delete _pTotalZeros2x2VlcDec; _pTotalZeros2x2VlcDec = NULL;}

	if (_pRunBeforeVlcEnc != NULL)
	    {delete _pRunBeforeVlcEnc; _pRunBeforeVlcEnc = NULL;}
	if (_pRunBeforeVlcDec != NULL)
	    {delete _pRunBeforeVlcDec; _pRunBeforeVlcDec = NULL;}

	if (_pBlkPattVlcEnc != NULL)
	    {delete _pBlkPattVlcEnc; _pBlkPattVlcEnc = NULL;}
	if (_pBlkPattVlcDec != NULL)
	    {delete _pBlkPattVlcDec; _pBlkPattVlcDec = NULL;}

	if (_pDeltaQPVlcEnc != NULL)
	    {delete _pDeltaQPVlcEnc; _pDeltaQPVlcEnc = NULL;}
	if (_pDeltaQPVlcDec != NULL)
	{
          IVlcDecoder * const _pDeltaQPVlcDecDel = _pDeltaQPVlcDec;	// JFO: Create safe copy to delete.
          _pDeltaQPVlcDec = NULL;
          delete _pDeltaQPVlcDecDel;
        }

	if (_pMbTypeVlcEnc != NULL)
	    {delete _pMbTypeVlcEnc; _pMbTypeVlcEnc = NULL;}
	if (_pMbTypeVlcDec != NULL)
	    {delete _pMbTypeVlcDec; _pMbTypeVlcDec = NULL;}

	/// The CAVLC codecs.
	if (_pCAVLC4x4 != NULL)
	    {delete _pCAVLC4x4; _pCAVLC4x4 = NULL;}
	if (_pCAVLC2x2 != NULL)
	    {delete _pCAVLC2x2; _pCAVLC2x2 = NULL;}

	/// Macroblock data objects.
	if (_pMb != NULL)
	    {delete[] _pMb; _pMb = NULL;}
	if (_Mb != NULL)
	    {delete[] _Mb; _Mb = NULL;}

	if (_autoIFrameIncluded != NULL)
	    {delete[] _autoIFrameIncluded; _autoIFrameIncluded = NULL;}

	/// Stream access.
	if (_pBitStreamWriter != NULL)
	    {delete _pBitStreamWriter; _pBitStreamWriter = NULL;}

	if (_pBitStreamReader != NULL)
	    {delete _pBitStreamReader; _pBitStreamReader = NULL;}

	/// Motion estimator and compensators.
	if (_pMotionEstimator != NULL)
	    {delete _pMotionEstimator; _pMotionEstimator = NULL;}

	/// Motion compensation vectors.
	if (_pMotionVectors != NULL)
	    {delete _pMotionVectors; _pMotionVectors = NULL;}

	if (_pMotionCompensator != NULL)
	    {delete _pMotionCompensator; _pMotionCompensator = NULL;}

	if (_pMotionPredictor != NULL)
	    {delete _pMotionPredictor; _pMotionPredictor = NULL;}

	/// Image plane encoders/decoders.
	if (_pIntraImgPlaneEncoder != NULL)
	    {delete _pIntraImgPlaneEncoder; _pIntraImgPlaneEncoder = NULL;}

	if (_pInterImgPlaneEncoder != NULL)
	    {delete _pInterImgPlaneEncoder; _pInterImgPlaneEncoder = NULL;}

	if (_pIntraImgPlaneDecoder != NULL)
		delete _pIntraImgPlaneDecoder;
	_pIntraImgPlaneDecoder = NULL;

	if (_pInterImgPlaneDecoder != NULL)
		delete _pInterImgPlaneDecoder;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	if (_pRateCntlPFrames != NULL)
	{
		_pRateCntlPFrames->Dump(H264V2_RATE_CNTL_PFRAMES);
		//    _pRateCntlPFrames->Dump();
		delete _pRateCntlPFrames;
		_pRateCntlPFrames = NULL;
	}//end if _pRateCntlPFrames...
	if (_pRateCntlIFrames != NULL)
	{
		_pRateCntlIFrames->Dump(H264V2_RATE_CNTL_IFRAMES);
		delete _pRateCntlIFrames;
		_pRateCntlIFrames = NULL;
	}//end if _pRateCntlIFrames...

  /// Region of Interest encoding.
  if (_roiMultiplier != NULL)
    delete[] _roiMultiplier;
  _roiMultiplier = NULL;

  _codecIsOpen = 0;
return(1);
}//end Close.

void H264v2Codec::Restart(void)
{
	_pictureCodingType = H264V2_INTRA;
	_frameNum = 0;				///< Reset the frame counter.
  /// _idrFrameNum does not require reseting.

  /// Zero the reference image. Note that the colour components are 
	/// held in contiguous mem.
	int imgSize = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
	memset(_pRLum, 0, imgSize * sizeof(short));

}//end Restart.

/*
-----------------------------------------------------------------------
  Private Implementation.
-----------------------------------------------------------------------
*/
/** Code non-picture nal types.
This method operates independently and therefore all the coding objects must be
instantiated and destroyed before and after the coding process. This is typically an
out-of-band process and therefore speed is not critical. The codec must NOT be open
for calls to this method i.e. _codecIsOpen = 0.
@param pCmp						: The stream memory to write to.
@param frameBitLimit	: The max number of bits to use.
@return								: 1 = success, 0 = failure.
*/
int H264v2Codec::CodeNonPicNALTypes(void* pCmp, int frameBitLimit)
{
	int allowedBits, bitsUsed;

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit;
	int ret = 1;	///< Return value default to success.
	_bitStreamSize = 0;

	/// This method uses the class members and therefore Open() must not be called before
	/// coding non-pic nal-types.
	if (_codecIsOpen)
	{
		_errorStr = "[H264V2::CodeNonPicNALTypes] Codec must not be open for non-picture nal types";
		return(0);
	}//end if _codecIsOpen...

	  /// Check which types are supported with this implementation.
	if ((_pictureCodingType != H264V2_SEQ_PARAM) && (_pictureCodingType != H264V2_PIC_PARAM))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Non-Nal picture type not supported";
		return(0);
	}//end if !H264V2_SEQ_PARAM...

	///----------------------------------------------------------------------------------------------
	/// Instantiate the mem objects required for the encoding.

	/// A stream writer.
	_pBitStreamWriter = new BitStreamWriterMSB();
	if (_pBitStreamWriter == NULL)
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate bit stream writer object";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if !_pBitStreamWriter...
	/// Set the stream writer to the compressed input parameter reference.
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pHeaderSignedVlcEnc = new ExpGolombSignedVlcEncoder();
	if ((_pHeaderUnsignedVlcEnc == NULL) || (_pHeaderSignedVlcEnc == NULL))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate vlc encoder objects";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if _pHeaderUnsignedVlcEnc...

	///----------------------------------------------------------------------------------------------
	/// Parameter set coding. The _currSeqParam and _currPicParam members determine the param sets
	/// to encode. From here the picture coding type is only H264V2_SEQ_PARAM or H264V2_PIC_PARAM.

	_nal._ref_idc = 3;

	if (_pictureCodingType == H264V2_SEQ_PARAM)
	{
		_nal._unit_type = NalHeaderH264::SeqParamSet;
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set sequence parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetSeqParamSet...
	}//end if H264V2_SEQ_PARAM...
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
	{
		_nal._unit_type = NalHeaderH264::PicParamSet;
		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set picture parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetPicParamSet...
	}//end else...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::CodeNonPicNALTypes] Cannot write start code to stream";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write the parameter set to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (_pictureCodingType == H264V2_SEQ_PARAM)
		runOutOfBits = WriteSeqParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currSeqParam);
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
		runOutOfBits = WritePicParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currPicParam);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write trailing bits to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	///----------------------------------------------------------------------------------------------
	/// Clean up memory objects.
H264V2_CNPNT_CLEAN_MEM:
	if (_pHeaderUnsignedVlcEnc != NULL)
	{
		delete _pHeaderUnsignedVlcEnc;
		_pHeaderUnsignedVlcEnc = NULL;
	}//end if _pHeaderUnsignedVlcEnc...
	if (_pHeaderSignedVlcEnc != NULL)
	{
		delete _pHeaderSignedVlcEnc;
		_pHeaderSignedVlcEnc = NULL;
	}//end if _pHeaderSignedVlcEnc...
	if (_pBitStreamWriter != NULL)
	{
		delete _pBitStreamWriter;
		_pBitStreamWriter = NULL;
	}//end if _pBitStreamWriter...

	return(ret);
}//end CodeNonPicNALTypes.

/** Set the Sequence parameter set.
Set one of the seq param sets defined by the index parameter where the
values are determined by interpreting the codec parameters.
@param index	:	Seq parameter set to modify [0..31].
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetSeqParamSet(int index)
{
	if (index > 31)
		return(0);

	_seqParam[index]._seq_parameter_set_id = index;					///< The index for this definition of sequence params [0..31].
	_seqParam[index]._profile_idc = 66;							///< Baseline profile = 66.
	_seqParam[index]._constraint_set0_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set1_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set2_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set3_flag = 0;							///< = 0.
	_seqParam[index]._level_idc = 20;							///< = 20 (Level num = 2, calculated as 10 x level num).
	_seqParam[index]._chroma_format_idc = 1;							///< Range = [0..3]. When not present = 1 (4:2:0).
	_seqParam[index]._residual_colour_transform_flag = 0;							///< = 0.
	_seqParam[index]._bit_depth_luma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/lum component).
	_seqParam[index]._bit_depth_chroma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/chr component).
	_seqParam[index]._qpprime_y_zero_transform_bypass_flag = 0;							///< If QP = 0, this flag indicates bypassing the transform process. When not present = 0.
	_seqParam[index]._seq_scaling_matrix_present_flag = 0;							///< = 0. No scaling matrices for baseline profile. Indicates existence of _seq_scaling_list_present_flag flags.
	/// Not initialised _seq_scaling_list_present_flag[8]			///< if _seq_scaling_matrix_present_flag, these indicate lists not present/present (0/1).
	_seqParam[index]._log2_max_frame_num_minus4 = _seqParamSetLog2MaxFrameNumMinus4;	///< Range = [0..12]. MaxFrameNum = 2^(_log2_max_frame_num_minus4 + 4) for slice _frame_num derivations.
	_seqParam[index]._pic_order_cnt_type = 2;							///< Range = [0..2]. 2 = 1-to-1 mapping. (Picture order count = frame num).
	_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = 0;							///< For B-Slice decoding.  There are no B-Slices in the baseline profile. 
	_seqParam[index]._delta_pic_order_always_zero_flag = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_non_ref_pic = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_top_to_bottom_field = 0;							///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = 0;							///< For B-Slice decoding.
	/// Not initialised _offset_for_ref_frame[256];						///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames = 1;							///< Max num of short-term and long-term ref frames.
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = 0;							///< Indicates allowed values of slice _frame_num.
	_seqParam[index]._frame_mbs_only_flag = 1;							///< = 1 (baseline profile). fields/frames = 0/1.
	_seqParam[index]._mb_adaptive_frame_field_flag = 0;							///< Indicates switching between frame and field macroblocks. When not present = 0.
	_seqParam[index]._direct_8x8_inference_flag = 0;							///< Methods for B-Slice motion vector decoding. There are no B-Slices in the baseline profile.
	_seqParam[index]._frame_cropping_flag = 0;							///< Indicates that the cropping params below follow in the stream.
	_seqParam[index]._frame_crop_left_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_right_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_top_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_bottom_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._vui_parameters_present_flag = 0;							///< vui parameters follow.

	if ((_width < 16) || (_height < 16))
		return(0);

	_seqParam[index]._pic_width_in_mbs_minus1 = (_width / 16) - 1;	///< Width of decoded pic in units of macroblocks. Derive lum and chr pic width from this variable.
	_seqParam[index]._pic_height_in_map_units_minus1 = (_height / 16) - 1;	///< Map units are 2 macroblocks for fields and 1 for frames. Derive lum and chr pic height from this variable.

	return(1);
}//end SetSeqParamSet.

/** Write the sequence parameter set to a bit stream.
The seq param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Sequence parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;

	/// Only baseline profile is supported: _profile_idc = 66.
//	if(_seqParam[index]._profile_idc != 66)
//	{
//		_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 0;
//		return(3);
//	}//end if _profile_idc not baseline...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (allowedBits < 24)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
	{
		bsw->Write(8, _seqParam[index]._profile_idc);						///< u(8)
		bsw->Write(_seqParam[index]._constraint_set0_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set1_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set2_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set3_flag);			///< u(1)
		bsw->Write(4, 0);																				///< u(4), reserved_zero_4bits.
		bsw->Write(8, _seqParam[index]._level_idc);							///< u(8)
	}//end if bsw...
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._seq_parameter_set_id);  ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._chroma_format_idc);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _residual_colour_transform_flag
		if (_seqParam[index]._chroma_format_idc == 3)
		{
			if (bsw)
				bsw->Write(_seqParam[index]._residual_colour_transform_flag); ///< u(1)
			bitsUsedSoFar++;
		}///end if _chroma_format_idc...

		/// _bit_depth_luma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_luma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _bit_depth_chroma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_chroma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// Two flags
		if (bsw)
		{
			bsw->Write(_seqParam[index]._qpprime_y_zero_transform_bypass_flag); ///< u(1)
			bsw->Write(_seqParam[index]._seq_scaling_matrix_present_flag);      ///< u(1)
		}//end if bsw...
		bitsUsedSoFar += 2;

		/// Scaling matricies
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				/// _seq_scaling_list_present_flag[8]
				if (bsw)
					bsw->Write(_seqParam[index]._seq_scaling_list_present_flag[i]); ///< u(1)
				bitsUsedSoFar++;

				bitCount = 0;
				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
				bitsUsedSoFar += bitCount;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_frame_num_minus4); ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_order_cnt_type
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_order_cnt_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._delta_pic_order_always_zero_flag);
		bitsUsedSoFar++;

		/// _offset_for_non_ref_pic
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_non_ref_pic);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _offset_for_top_to_bottom_field
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_top_to_bottom_field);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_ref_frame[i]);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_WSPS_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _gaps_in_frame_num_value_allowed_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._gaps_in_frame_num_value_allowed_flag);
	bitsUsedSoFar++;

	/// _pic_width_in_mbs_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_width_in_mbs_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_height_in_map_units_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_height_in_map_units_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _frame_mbs_only_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_mbs_only_flag);
	bitsUsedSoFar++;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._mb_adaptive_frame_field_flag);
		bitsUsedSoFar++;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._direct_8x8_inference_flag);
	bitsUsedSoFar++;

	/// _frame_cropping_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_cropping_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_left_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_right_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_right_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_top_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_top_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_bottom_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_bottom_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._vui_parameters_present_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: Implement VUI encoding.
	}//end if _vui_parameters_present_flag...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSeqParamSet.

/// This method has not been tested and at first glance does not look correct
int H264v2Codec::WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, bitCount;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			nextScale = scalingList[j];

			/// deltaScale
			int deltaScale = nextScale - lastScale;
			bitCount = _pHeaderSignedVlcEnc->Encode(deltaScale);  ///< se(v)
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				return(bitsUsed);
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsed += bitCount;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end WriteSeqParamScalingList.

/** Read the sequence parameter set from the bit stream.
This impementation reads sequence parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to seq param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits, i;
	int li;
	int pi;
	int set0_flag;
	int set1_flag;
	int set2_flag;
	int set3_flag;
	int index;

	SeqParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "H264V2:[H264Codec::ReadSeqParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (remainingBits < 24)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// Temporarily read up to the _seq_parameter_set_id that defines the index into the
	/// _seqParam[] array.

	pi = bsr->Read(8);																		///< u(8):_profile_idc
	/// Only baseline profile is supported: _profile_idc = 66.
//	if(pi != 66)
//	{
//		_errorStr = "[H264Codec::ReadSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 8;
//		return(2);
//	}//end if pi not baseline...
	set0_flag = bsr->Read();															///< u(1):_constraint_set0_flag
	set1_flag = bsr->Read();															///< u(1):_constraint_set1_flag
	set2_flag = bsr->Read();															///< u(1):_constraint_set2_flag
	set3_flag = bsr->Read();															///< u(1):_constraint_set3_flag
	bsr->Read(4);																							///< u(4), reserved_zero_4bits ignored.
	li = bsr->Read(8);																		///< u(8):_level_idc
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the array index.
	if ((index < 0) || (index > 31))
	{
		_errorStr = "[H264Codec::ReadSeqParamSet] Sequence parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_seqParam[index]));

	/// The array index is now known and within range so the structure can be checked and loaded from the
	/// temporary variables.
	_seqParam[index]._profile_idc = pi;
	_seqParam[index]._constraint_set0_flag = set0_flag;
	_seqParam[index]._constraint_set1_flag = set1_flag;
	_seqParam[index]._constraint_set2_flag = set2_flag;
	_seqParam[index]._constraint_set3_flag = set3_flag;
	_seqParam[index]._level_idc = li;
	_seqParam[index]._seq_parameter_set_id = index;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		_seqParam[index]._chroma_format_idc = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		if (_seqParam[index]._chroma_format_idc == 3)
		{
			_seqParam[index]._residual_colour_transform_flag = bsr->Read(); ///< u(1)
			bitsUsedSoFar++;
		}//end if _chroma_format_idc...

		  /// _bit_depth_luma_minus8
		_seqParam[index]._bit_depth_luma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _bit_depth_chroma_minus8
		_seqParam[index]._bit_depth_chroma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Two flags.
		_seqParam[index]._qpprime_y_zero_transform_bypass_flag = bsr->Read(); ///< u(1)
		_seqParam[index]._seq_scaling_matrix_present_flag = bsr->Read(); ///< u(1)
		bitsUsedSoFar += 2;

		/// _seq_scaling_list_present_flag[]
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				_seqParam[index]._seq_scaling_list_present_flag[i] = bsr->Read(); ///< u(1)
				bitsUsedSoFar++;

				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSPS_RUNOUTOFBITS_READ;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	_seqParam[index]._log2_max_frame_num_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_order_cnt_type
	_seqParam[index]._pic_order_cnt_type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		_seqParam[index]._delta_pic_order_always_zero_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_non_ref_pic
		_seqParam[index]._offset_for_non_ref_pic = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_top_to_bottom_field
		_seqParam[index]._offset_for_top_to_bottom_field = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			_seqParam[index]._offset_for_ref_frame[i] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSPS_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSPS_RUNOUTOFBITS_READ;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	_seqParam[index]._num_ref_frames = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _gaps_in_frame_num_value_allowed_flag
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_width_in_mbs_minus1
	_seqParam[index]._pic_width_in_mbs_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_height_in_map_units_minus1
	_seqParam[index]._pic_height_in_map_units_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_mbs_only_flag
	_seqParam[index]._frame_mbs_only_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		_seqParam[index]._mb_adaptive_frame_field_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	_seqParam[index]._direct_8x8_inference_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_cropping_flag
	_seqParam[index]._frame_cropping_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		_seqParam[index]._frame_crop_left_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_right_offset
		_seqParam[index]._frame_crop_right_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_top_offset
		_seqParam[index]._frame_crop_top_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_bottom_offset
		_seqParam[index]._frame_crop_bottom_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	_seqParam[index]._vui_parameters_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: ReadSeqParamVuiParams() does not work properly and must be debugged.
			//numBits = ReadSeqParamVuiParams(bsr);
			//bitsUsedSoFar += numBits;
			//if( bitsUsedSoFar > remainingBits )
			//	goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Dummy read all the bits except the last one to leave the bsr pointer on the last bit.
		int pos = bsr->GetStreamBitPos();
		numBits = remainingBits - bitsUsedSoFar - 1;
		bsr->Read(numBits);
		/// Search backwards until the trailing stop bit is found.
		pos = bsr->GetStreamBitPos();
		while (bsr->Peek(pos, 1) != 1)
		{
			pos++;
			numBits--;
		}//end while Peek...
		/// Set the bsr to point at the stop bit.
		bsr->Seek(pos);
		bitsUsedSoFar += numBits;

	}//end if _vui_parameters_present_flag...

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_seqParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSeqParamSet.

/// This method has not been tested.
int H264v2Codec::ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, numBits;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			/// deltaScale 
			int deltaScale = _pHeaderSignedVlcDec->Decode(bsr); ///< se(v)
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				return(bitsUsed);
			bitsUsed += numBits;

			nextScale = (lastScale + deltaScale + 256) % 256;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		if (nextScale == 0)
			scalingList[j] = lastScale;
		else
			scalingList[j] = nextScale;
		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end ReadSeqParamScalingList.

/** Read the vui parameters from a sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	/// Aspect ratio info
	unsigned int aspect_ratio_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (aspect_ratio_info_present_flag)
	{
		unsigned int aspect_ratio_idc = bsr->Read(8); ///< u(8)
		bitsUsed += 8;
		if (aspect_ratio_idc == 255) ///< Extended_SAR
		{
			unsigned int sar_width = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
			unsigned int sar_height = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
		}//end if aspect_ratio_idc...
	}//end if aspect_ratio_info_present_flag...

	/// Overscan info
	unsigned int overscan_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (overscan_info_present_flag)
	{
		unsigned int overscan_appropriate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if overscan_info_present_flag...

	/// Video signal type info
	unsigned int video_signal_type_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (video_signal_type_present_flag)
	{
		unsigned int video_format = bsr->Read(3); ///< u(3)
		bitsUsed += 3;
		unsigned int video_full_range_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int colour_description_present_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		if (colour_description_present_flag)
		{
			unsigned int colour_primaries = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int transfer_characteristics = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int matrix_coefficients = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
		}//end if colour_description_present_flag...
	}//end if video_signal_type_present_flag...

	/// Chroma location info
	unsigned int chroma_loc_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (chroma_loc_info_present_flag)
	{
		unsigned int chroma_sample_loc_type_top_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int chroma_sample_loc_type_bottom_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if chroma_loc_info_present_flag...

	/// Timing info
	unsigned int timing_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (timing_info_present_flag)
	{
		unsigned int num_units_in_tick = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int time_scale = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int fixed_frame_rate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if timing_info_present_flag...

	/// HRD parameter info
	unsigned int nal_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (nal_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if nal_hrd_parameters_present_flag...
	unsigned int vcl_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (vcl_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if vcl_hrd_parameters_present_flag...
	if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
	{
		unsigned int low_delay_hrd_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if nal_hrd_parameters_present_flag...

	/// Picture structure info
	unsigned int pic_struct_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;

	/// Bit stream restriction info
	unsigned int bitstream_restriction_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (bitstream_restriction_flag)
	{
		unsigned int motion_vectors_over_pic_boundaries_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int max_bytes_per_pic_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_bits_per_mb_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_horizontal = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_vertical = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int num_reorder_frames = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_dec_frame_buffering = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if bitstream_restriction_flag...

	return(bitsUsed);
}//end ReadSeqParamVuiParams.

/** Read the hrd parameters from a vui sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiHrdParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	unsigned int cpb_cnt_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
	bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();

	unsigned int bit_rate_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	unsigned int cpb_size_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	for (unsigned int schedSelIdx = 0; schedSelIdx <= cpb_cnt_minus1; schedSelIdx++)
	{
		/// This is a dummy method but the actual method will fill bit_rate_value_minus1[schedSelIdx] array.
		unsigned int bit_rate_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cpb_size_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cbr_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end for schedSelIdx...

	unsigned int initial_cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int dpb_output_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int time_offset_length = bsr->Read(5); ///< u(5)
	bitsUsed += 5;

	return(bitsUsed);
}//endReadSeqParamVuiHrdParams. 

/** Set the Picture parameter set.
Set one of the pic param sets defined by the index parameters where the
values are determined by interpreting the codec parameters.
@param index	:	Pic parameter set to modify [0..255].
@param seqRef	: Seq param set to reference.
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetPicParamSet(int index, int seqRef)
{
	if ((index > 255) || (seqRef > 31))
		return(0);

	_picParam[index]._pic_parameter_set_id = index;	///< The index for this definition of picture params [0..255].
	_picParam[index]._seq_parameter_set_id = seqRef;	///< This pic param set refers to this seq param set. Range = [0..31].
	_picParam[index]._entropy_coding_mode_flag = 0;			///< Baseline profile = 0. CAVLC/CABAC = 0/1.
	_picParam[index]._pic_order_present_flag = 0;			///< Pic order count syntax elements are present in the slice header.
	_picParam[index]._num_slice_groups_minus1 = 0;			///< = 0 (baseline profile). Num of slice groups for a pic.
	_picParam[index]._slice_group_map_type = 0;			///< Defines map units to slice groups. Range = [0..6].
	/// Not initialised: _run_length_minus1[7];									///< Slice group mapping.
	/// Not initialised: _top_left[7];													///< Slice group mapping.
	/// Not initialised: _bottom_right[7];											///< Slice group mapping.
	_picParam[index]._slice_group_change_direction_flag = 0;			///< Slice group mapping.
	_picParam[index]._slice_group_change_rate_minus1 = 0;			///< Slice group mapping.
	/// Not initialised: _slice_group_id[7];										///< Slice group mapping.
	_picParam[index]._num_ref_idx_l0_active_minus1 = 0;			///< Max ref index for ref pic list0.
	_picParam[index]._num_ref_idx_l1_active_minus1 = 0;			///< Max ref index for ref pic list1. (For B-Slices)
	_picParam[index]._weighted_pred_flag = 0;			///< Indicates weighted prediction applied to P-Slices.
	_picParam[index]._weighted_bipred_idc = 0;			///< Weighted prediction type applied to B-Slices.
	_picParam[index]._pic_init_qp_minus26 = 0;			///< Initial value of lum SliceQP - 26 for each slice. The slice_qp_delta modifies this value. Rng = [-26..25].
	_picParam[index]._pic_init_qs_minus26 = 0;			///< For SP and SI slices.
	_picParam[index]._chroma_qp_index_offset = 0;			///< Offset added to lum QP (and QS) for Cb chr QP values. Rng = [-12..12].
	_picParam[index]._second_chroma_qp_index_offset = 0;			///< For Cr chr QP. When not present = _chroma_qp_index_offset above.
	_picParam[index]._deblocking_filter_control_present_flag = 0;			///< Indicates presence of elements in slice header to change the characteristics of the deblocking filter.
	_picParam[index]._constrained_intra_pred_flag = 1;			///< = 1. Indicates that intra macroblock prediction can only be done from other intra macroblocks. 
	_picParam[index]._redundant_pic_cnt_present_flag = 0;			///< Indicates that redundant pic count elements are in the slice header.
	_picParam[index]._transform_8x8_mode_flag = 0;			///< = 0. Indicates 8x8 transform is used. When not present = 0.
	_picParam[index]._pic_scaling_matrix_present_flag = 0;			///< = 0. Indicates params are present to modify the scaling lists specified in the seq param sets.
	/// Not initialised:_pic_scaling_list_present_flag[8];			///< Scaling list syntax structure present for scaling list i = 0..7.

	_picParam[index]._pic_size_in_map_units_minus1 = ((_width / 16)*(_height / 16)) - 1;	///< Num of map units (macroblocks for frames) in the pic. Macroblock width * height.

	return(1);
}//end SetPicParamSet.

/** Write the picture parameter set to a bit stream.
The pic param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Picture parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// _pic_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._pic_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._seq_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _entropy_coding_mode_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._entropy_coding_mode_flag);
	bitsUsedSoFar++;

	/// _pic_order_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._pic_order_present_flag);
	bitsUsedSoFar++;

	/// _num_slice_groups_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_slice_groups_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_WPPS_MODEERROR_WRITE;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l0_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _num_ref_idx_l1_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l1_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _weighted_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._weighted_pred_flag);
	bitsUsedSoFar++;

	/// _weighted_bipred_idc
	if ((bitsUsedSoFar + 2) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(2, _picParam[index]._weighted_bipred_idc);
	bitsUsedSoFar += 2;

	/// _pic_init_qp_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qp_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_init_qs_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qs_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _chroma_qp_index_offset
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._chroma_qp_index_offset);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _deblocking_filter_control_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._deblocking_filter_control_present_flag);
	bitsUsedSoFar++;

	/// _constrained_intra_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._constrained_intra_pred_flag);
	bitsUsedSoFar++;

	/// _redundant_pic_cnt_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._redundant_pic_cnt_present_flag);
	bitsUsedSoFar++;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WPPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WPPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WPPS_MODEERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WritePicParamSet.

/** Read the picture parameter set from the bit stream.
This impementation reads picture parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to pic param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits;
	PicParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "[H264Codec::ReadPicParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// _pic_parameter_set_id
	int index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the pic param array index.
	if ((index < 0) || (index > 255))
	{
		_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_picParam[index]));

	/// The decoded index identifies the param set to use.
	_picParam[index]._pic_parameter_set_id = index;

	/// _seq_parameter_set_id
	_picParam[index]._seq_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// Range check on the seq param array index. This does not test if the data in the _seqParam[]
	/// array for this id is valid.
	if ((_picParam[index]._seq_parameter_set_id < 0) || (_picParam[index]._seq_parameter_set_id > 31))
	{
		_errorStr = "H264V2:[H264Codec::ReadPicParamSet] Sequence parameter set index of picture parameter set is out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

	/// _entropy_coding_mode_flag
	_picParam[index]._entropy_coding_mode_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_order_present_flag
	_picParam[index]._pic_order_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_slice_groups_minus1
	_picParam[index]._num_slice_groups_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_RPPS_NOMODE_READ;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	_picParam[index]._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_ref_idx_l1_active_minus1
	_picParam[index]._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_pred_flag
	_picParam[index]._weighted_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_bipred_idc
	_picParam[index]._weighted_bipred_idc = bsr->Read(2);
	bitsUsedSoFar += 2;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qp_minus26
	_picParam[index]._pic_init_qp_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qs_minus26
	_picParam[index]._pic_init_qs_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _chroma_qp_index_offset
	_picParam[index]._chroma_qp_index_offset = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _deblocking_filter_control_present_flag
	_picParam[index]._deblocking_filter_control_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _constrained_intra_pred_flag
	_picParam[index]._constrained_intra_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _redundant_pic_cnt_present_flag
	_picParam[index]._redundant_pic_cnt_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_picParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RPPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RPPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RPPS_NOMODE_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadPicParamSet.

/** Get the codec parameters.
Load the codec params from the picture param set indexed by
the input param. The sequence param set is implied in the referenced
pic param set. The pic/seq param set must be previously defined
prior to calling this method.
@param picParamSet	:	Pic parameter set to get from [0..255].
@return							: Success = 1, failure = 0.
*/
int H264v2Codec::GetCodecParams(int picParamSet)
{
	///----------- Some parameter set range checking ------------------------------
	if ((picParamSet < 0) || (picParamSet > 255))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set out of range";
		return(0);
	}//end if picParamSet...
	if (_picParam[picParamSet]._pic_parameter_set_id != picParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set mismatch";
		return(0);
	}//end if _pic_parameter_set_id...
	int seqParamSet = _picParam[picParamSet]._seq_parameter_set_id;
	if ((seqParamSet < 0) || (seqParamSet > 31))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set out of range";
		return(0);
	}//end if seqParamSet...
	if (_seqParam[seqParamSet]._seq_parameter_set_id != seqParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set mismatch";
		return(0);
	}//end if _seq_parameter_set_id...
	/// Modify the codec seq param set to that associated with this pic param set.
	_currSeqParam = seqParamSet;

	///----------- Extract params of interest for codec -----------------------
	/// Get width and height in pels.
	_width = (_seqParam[seqParamSet]._pic_width_in_mbs_minus1 + 1) * 16;
	_height = (_seqParam[seqParamSet]._pic_height_in_map_units_minus1 + 1) * 16;
	_seqParamSetLog2MaxFrameNumMinus4 = _seqParam[seqParamSet]._log2_max_frame_num_minus4;

	///----------- Check params for this implementation -----------------------

	/// Sequence parameter implementation.
	if ((_seqParam[seqParamSet]._profile_idc != 66) ||
		(_seqParam[seqParamSet]._constraint_set0_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set1_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set2_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set3_flag != 0) ||
		(_seqParam[seqParamSet]._level_idc != 20) ||
		(_seqParam[seqParamSet]._chroma_format_idc != 1) ||
		(_seqParam[seqParamSet]._bit_depth_luma_minus8 != 0) ||
		(_seqParam[seqParamSet]._bit_depth_chroma_minus8 != 0) ||
		(_seqParam[seqParamSet]._qpprime_y_zero_transform_bypass_flag != 0) ||
		(_seqParam[seqParamSet]._seq_scaling_matrix_present_flag != 0) ||
		(_seqParam[seqParamSet]._pic_order_cnt_type != 2) ||
		(_seqParam[seqParamSet]._num_ref_frames != 1) ||
		(_seqParam[seqParamSet]._gaps_in_frame_num_value_allowed_flag != 0) ||
		(_seqParam[seqParamSet]._frame_mbs_only_flag != 1) ||
		(_seqParam[seqParamSet]._mb_adaptive_frame_field_flag != 0) ||
		(_seqParam[seqParamSet]._direct_8x8_inference_flag != 0) ||
		(_seqParam[seqParamSet]._frame_cropping_flag != 0) ||
		(_seqParam[seqParamSet]._vui_parameters_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameters not implemented";
		return(0);
	}//end if _profile_idc...

	/// Picture parameter implementation.
	if ((_picParam[picParamSet]._entropy_coding_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_order_present_flag != 0) ||
		(_picParam[picParamSet]._num_slice_groups_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l0_active_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l1_active_minus1 != 0) ||
		(_picParam[picParamSet]._weighted_pred_flag != 0) ||
		(_picParam[picParamSet]._weighted_bipred_idc != 0) ||
		(_picParam[picParamSet]._constrained_intra_pred_flag != 1) ||
		(_picParam[picParamSet]._redundant_pic_cnt_present_flag != 0) ||
		(_picParam[picParamSet]._transform_8x8_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_scaling_matrix_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameters not implemented";
		return(0);
	}//end if _profile_idc...

	return(1);
}//end GetCodecParams.

/** Write the NAL header to a bit stream.
The NAL header data must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit overflow
will occur before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (allowedBits >= 8)
	{
		if (bsw)
		{
			bsw->Write(1, 0);												///< Forbidden zero bit f(1).
			bsw->Write(2, (_nal._ref_idc & 3));			///< u(2).		
			bsw->Write(5, (_nal._unit_type & 31));	///< u(5).		
		}//end if bsw != NULL...
	}//end if allowedBits...
	else
	{
		_errorStr = "H264V2:[WriteNALHeader] Bits required exceeds max available for NAL header";
		*bitsUsed = 0;
		return(1);
	}///end else...

	*bitsUsed = 8;
	return(0);
}//end WriteNALHeader.

/** Read the NAL header from the bit stream.
This impementation reads the NAL header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (remainingBits >= 8)
	{
		bsr->Read();													///< Discard forbidden zero bit f(1).
		_nal._ref_idc = 3 & bsr->Read(2);		///< u(2).
		_nal._unit_type = 31 & bsr->Read(5);	///< u(5).
	}//end if remainingBits...
	else
	{
		_errorStr = "H264V2:[ReadNALHeader] Insufficient bits to decode the NAl header";
		*bitsUsed = 0;
		return(1);
	}//end else...

	*bitsUsed = 8;
	return(0);
}//end ReadNALHeader.

/** Write the slice layer header to a bit stream.
The encodings of all the slice data must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. Each write checks if a bit overflow will occur before writing.
The check is sufficiently frequent to warrant an early exit GOTO
statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int	  bitCount;
	int   bitsUsedSoFar = 0;
	char  errInfo[64];
	char  buff[64];

		/// Limited implementation of modes and types for Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_WSLH_MODEERROR_WRITE;

	///-------------------------- Addr of first macroblock -----------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._first_mb_in_slice);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_first_mb_in_slice=");
		sprintf((char *)buff, "%d", _slice._first_mb_in_slice);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._first_mb_in_slice, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Slice Type -------------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._type);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_type=");
		sprintf((char *)buff, "%d", _slice._type);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._type, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Pic Param Set Id --------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._pic_parameter_set_id);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_pic_parameter_set_id=");
		sprintf((char *)buff, "%d", _slice._pic_parameter_set_id);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._pic_parameter_set_id, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Frame Number -----------------------------------------------
	bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	if ((bitsUsedSoFar + bitCount) <= allowedBits)
	{
		if (bsw)
			bsw->Write(bitCount, _slice._frame_num);
	}//end if bitsUsedSoFar...
	else
		goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	bitsUsedSoFar += bitCount;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		if ((bitsUsedSoFar + 2) <= allowedBits)	///< Both flags together.
		{
			if (bsw)
				bsw->Write(_slice._field_pic_flag);
			bitsUsedSoFar++;
			if (_slice._field_pic_flag)
			{
				if (bsw)
					bsw->Write(_slice._bottom_field_flag);
				bitsUsedSoFar++;
			}//end if _field_pic_flag...
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._idr_pic_id);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
				{
					if (bitCount <= 32)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					else
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetExtCode(), _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bsw...
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_idr_pic_id=");
			sprintf((char *)buff, "%d", _slice._idr_pic_id);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._idr_pic_id, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _slice._pic_order_cnt_lsb);
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt_bottom);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt_bottom=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt_bottom);
				strcat(errInfo, buff);
				// strcat(errInfo, itoa(_slice._delta_pic_order_cnt_bottom, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[0]);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_delta_pic_order_cnt[0]=");
			sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[0]);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[0], buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[1]);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt[1]=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[1]);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[1], buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._redundant_pic_cnt);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_redundant_pic_cnt=");
			sprintf((char *)buff, "%d", _slice._redundant_pic_cnt);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._redundant_pic_cnt, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._direct_spatial_mv_pred_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::B_Slice) ||
		(_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._num_ref_idx_active_override_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._num_ref_idx_active_override_flag)
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l0_active_minus1);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_num_ref_idx_l0_active_minus1=");
				sprintf((char *)buff, "%d", _slice._num_ref_idx_l0_active_minus1);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._num_ref_idx_l0_active_minus1, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice))
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l1_active_minus1);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_num_ref_idx_l1_active_minus1=");
					sprintf((char *)buff, "%d", _slice._num_ref_idx_l1_active_minus1);
					strcat(errInfo, buff);
					//strcat(errInfo, itoa(_slice._num_ref_idx_l1_active_minus1, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._ref_pic_list_reordering_flag_l0);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._reordering_of_pic_nums_idc);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_reordering_of_pic_nums_idc=");
					sprintf((char *)buff, "%d", _slice._reordering_of_pic_nums_idc);
					strcat(errInfo, buff);
					// strcat(errInfo, itoa(_slice._reordering_of_pic_nums_idc, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{

					// TODO: Prepare list 0 reordering with _slice._abs_diff_pic_num_minus1.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._abs_diff_pic_num_minus1);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_abs_diff_pic_num_minus1=");
						sprintf((char *)buff, "%d", _slice._abs_diff_pic_num_minus1);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._abs_diff_pic_num_minus1, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{

					// TODO: Prepare list 0 reordering with _slice._long_term_pic_num.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._long_term_pic_num);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_long_term_pic_num=");
						sprintf((char *)buff, "%d", _slice._long_term_pic_num);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._long_term_pic_num, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...

	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			if ((bitsUsedSoFar + 2) <= allowedBits)
			{
				if (bsw)
				{
					bsw->Write(_slice._no_output_of_prior_pics_flag);
					bsw->Write(_slice._long_term_reference_flag);
				}//end if bsw...
				bitsUsedSoFar += 2;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if IDR_Slice...
		else
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._adaptive_ref_pic_marking_mode_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_WSLH_MODEERROR_WRITE;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation ----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._cabac_init_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_cabac_init_idc=");
			sprintf((char *)buff, "%d", _slice._cabac_init_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._cabac_init_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qp_delta);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_qp_delta=");
		sprintf((char *)buff, "%d", _slice._qp_delta);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._qp_delta, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SI_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._sp_for_switch_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if SP_Slice...

		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qs_delta);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_qs_delta=");
			sprintf((char *)buff, "%d", _slice._qs_delta);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._qs_delta, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._disable_deblocking_filter_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_disable_deblocking_filter_idc=");
			sprintf((char *)buff, "%d", _slice._disable_deblocking_filter_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._disable_deblocking_filter_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._alpha_c0_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_alpha_c0_offset_div2=");
				sprintf((char *)buff, "%d", _slice._alpha_c0_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._alpha_c0_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._beta_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_beta_offset_div2=");
				sprintf((char *)buff, "%d", _slice._beta_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._beta_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _disable_deblocking_filter_idc...

	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_WSLH_MODEERROR_WRITE;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSLH_RUNOUTOFBITS_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSLH_VLCERROR_WRITE:
	strcpy(_errorInfo, "[H264v2Codec::WriteSliceLayerHeader] Vlc encoder error: ");
	strcat(_errorInfo, errInfo);
	_errorStr = _errorInfo;
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WSLH_MODEERROR_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceLayerHeader.

/** Read the slice layer header from the bit stream.
This impementation reads slice header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int numBits;

	if (bsr == NULL)
	{
		_errorStr = "[H264V2::ReadSliceLayerHeader] No bit stream reader";
		*bitsUsed = 0;
		return(2);
	}//end if !bsr...

	///-------------------------- Addr of first macroblock -----------------------------------
	_slice._first_mb_in_slice = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Slice Type -------------------------------------------------
	_slice._type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	/// Limited implementation of slice types and modes for the Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_RSLH_NOMODE_READ;

	///-------------------------- Pic Param Set Id --------------------------------------------
	_slice._pic_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Frame Number ----------------------------------------------
	numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	_slice._frame_num = bsr->Read(numBits);
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		_slice._field_pic_flag = bsr->Read();
		bitsUsedSoFar++;
		if (_slice._field_pic_flag)
		{
			_slice._bottom_field_flag = bsr->Read();
			bitsUsedSoFar++;
		}//end if _field_pic_flag...
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		_slice._idr_pic_id = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		_slice._pic_order_cnt_lsb = bsr->Read(numBits);
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt_bottom = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...

	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		_slice._delta_pic_order_cnt[0] = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt[1] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		_slice._redundant_pic_cnt = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._direct_spatial_mv_pred_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::P_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._num_ref_idx_active_override_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._num_ref_idx_active_override_flag)
		{
			_slice._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
			{
				_slice._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._ref_pic_list_reordering_flag_l0 = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				_slice._reordering_of_pic_nums_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{
					_slice._abs_diff_pic_num_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._abs_diff_pic_num_minus1.
					goto H264V2_RSLH_NOMODE_READ;

				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{
					_slice._long_term_pic_num = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._long_term_pic_num.
					goto H264V2_RSLH_NOMODE_READ;

				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...
	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			_slice._no_output_of_prior_pics_flag = bsr->Read();
			_slice._long_term_reference_flag = bsr->Read();
			bitsUsedSoFar += 2;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if IDR_Slice...
		else
		{
			_slice._adaptive_ref_pic_marking_mode_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_RSLH_NOMODE_READ;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation  ---------------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._cabac_init_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	_slice._qp_delta = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::SI_Slice) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			_slice._sp_for_switch_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if SP_Slice...

		_slice._qs_delta = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		_slice._disable_deblocking_filter_idc = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			_slice._alpha_c0_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			_slice._beta_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _disable_deblocking_filter_idc...
	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_RSLH_NOMODE_READ;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSLH_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSLH_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RSLH_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSliceLayerHeader.

/** Write trailing bits to a bit stream.
A stop 1 bit is written and then zero bits are written until a byte boundary. Each
write checks if a bit overflow will occur before writing the stop bit. The zeros
are not counted in the bitsUsed. If the input stream param is NULL then this method
is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0.
*/
int H264v2Codec::WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	/// Write the stop bit.
	if (allowedBits < 1)
	{
		_errorStr = "H264V2:[WriteTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if allowedBits...
	if (bsw)
		bsw->Write(1);
	bitsUsedSoFar++;

	/// Write zeros to the end of the byte. Do not count the trailing zeros.
	if (bsw)
	{
		int toByteBoundary = (bsw->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Do not allow the last byte to be 0x00
			bsw->Write(toByteBoundary, 0);
		//bitsUsedSoFar += toByteBoundary;
	}//end if bsw...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}// end WriteTrailingBits.

/** Read trailing bits from the bit stream.
This impementation reads the trailing bit encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 3.
*/
int H264v2Codec::ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int bit = 1;

	if (remainingBits < 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if remainingBits...

	/// Read stop bit.
	if (bsr)
		bit = bsr->Read();
	bitsUsedSoFar++;
	if (bit != 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] No stop bit detected";
		*bitsUsed = bitsUsedSoFar;
		return(3);
	}//end if !stop bit...

	/// Read zeros up to the end of the byte. Do not count the trailing zeros.
	if (bsr)
	{
		int toByteBoundary = (bsr->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Only read zeros within the same byte as the stop bit.
		{
			bit = bsr->Read(toByteBoundary);
			//bitsUsedSoFar += toByteBoundary;
			if (bit != 0)
			{
				_errorStr = "H264V2:[ReadTrailingBits] Missing trailing zeros";
				*bitsUsed = bitsUsedSoFar;
				return(3);
			}//end if !zero bits...
		}//end if toByteBoundary...
	}//end if bsr...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadTrailingBits.

/** Insert start code emulation prevention codes.
Scan the entire stream, excluding the 32 bit actual start code, and check
for 24 bit 0x000000 - 0x000003 sequences. Replace them with 32 bit
0x00000300 - 0x00000303 sequences. The extra byte (8 bits) for each
emulation code is excluded from the number of allowed bits but is added
to the total consumed bits. [NB: Care must be taken when checking for
running out of bits to allow for these extra codes.] This method should
only be called once the entire frame has been encoded.
@param bsw	        : Stream to write into.
@param startOffset  : Start evaluating the stream from a byte offset.
@return			        : Return the number of extra bits inserted.
*/
int H264v2Codec::InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset)
{
	if (bsw == NULL)
		return(0);

	int count = 0;

	unsigned char*  streamHead = (unsigned char*)(bsw->GetStream());
	unsigned char*  stream = &(streamHead[startOffset]);

	/// It is assumed that the stream is fully encoded and the trailing bits have been added
	/// to ensure byte alignement of the stream. Therefore the current stream byte pos is the 
	/// number of encoded bytes in the stream.
	int  endPos = bsw->GetStreamBytePos() - 1 - startOffset;
	if (endPos < 2) return(0);

	/// Find the occurrance of the start code emulation then shift down by copying backwards from the end. Note
	/// that 1st 4 bytes are the start code 0x00000001.
	for (int pos = 6; pos <= endPos; pos++)
	{
		if ((stream[pos] & 0xFC) == 0) ///< Check for 0, 1, 2 or 3.
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0)) ///< Check 2 preceeding bytes are zero.
			{
				for (int i = endPos; i >= pos; i--) ///< Shift down by 1 byte.
					stream[i + 1] = stream[i];
				stream[pos] = 0x03; ///< Insert emulation prevention code.
				pos++;              ///< Continue from new shifted position.
				endPos++;           ///< Last byte is now shifted by 1 position.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end InsertEmulationPrevention.

/** Remove start code emulation prevention codes.
Scan the entire stream and check for 24 bit 0x000003 sequence
and remove the 0x03 byte from the stream. This method should
only be called once before decoding the entire frame.
@param bsr	: Stream to read from.
@return			: Return the number of extra bits removed.
*/
int H264v2Codec::RemoveEmulationPrevention(IBitStreamReader* bsr)
{
	if (bsr == NULL)
		return(0);

	int count = 0;

	unsigned char*  stream = (unsigned char*)(bsr->GetStream());
	int             bits = bsr->GetStreamBitSize();
	int             endPos = (bits / 8) - 1;
	if ((bits % 8) != 0)
		endPos++;

	/// Find the 1st occurrence of the emulation prevention code.
	int pos;
	for (pos = 2; pos <= endPos; pos++)
	{
		if (stream[pos] == 0x03) ///< Emulation prevention code = 0x03...
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0))  ///< ...and is preceeded by 2 zero bytes.
			{
				/// Shift remaining bytes up by 1 byte.
				for (int i = pos; i < endPos; i++)
					stream[i] = stream[i + 1];
				pos++;    ///< Skip one to prevent trapping a 0x00 followed by a 0x03 in the actual stream.
				endPos--; ///< Last byte was shifted by 1.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end RemoveEmulationPrevention.

/** Write the slice data layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes every macroblock encoding in top-left
to bottom-right order. Each write checks if a bit overflow will occur
before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is
used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int mb, i;
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// All macroblocks are written in order.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// ------------------------ Code the slice data -----------------------------------
	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		if (!pMb->_skip)	///< Encoding must set the _skip flag even for Intra macroblocks.
		{
			if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
				(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
			{
				/// ------------------------ Code the skip run -----------------------------------
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
				if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
					goto H264V2_VLCERROR_WRITE;
				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_RUNOUTOFBITS_WRITE;
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				bitsUsedSoFar += bitCount;

				_mb_skip_run = 0;	///< ...and reset.
			}//end if !I_Slice...

			/// ------------------------ Code the macroblock data ------------------------------------
			/// Only non-skipped macroblocks call this method.
			int ret = WriteMacroBlockLayer(bsw, pMb, allowedBits - bitsUsedSoFar, &bitCount);
			if (ret) ///< An error has occurred.
			{
				/// _errorStr was set in the WriteMacroBlockLayer() method.
				*bitsUsed = bitsUsedSoFar + bitCount;
				return(ret);
			}//end if ret...
			bitsUsedSoFar += bitCount;
		}//end if !_skip...
		else
		{
			_mb_skip_run++;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end else...

	}//end for mb...

	/// If the final macroblocks of the slice were all skipped then a skip run must be coded onto the stream.
	if (_mb_skip_run)
	{
		if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end if !I_Slice...
	}//end if _mb_skip_run...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceDataLayer.

/** Read the slice data layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr		: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed		: Return the actual bits extracted.
@return			: Run out of bits = 1, more bits available = 0, error = 2.*/
int H264v2Codec::ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int mb, i;
	int bitsUsedSoFar = 0;
	int numBits;

	/// Whip through each macroblock. Extract the encoded macroblock
	/// from the bit stream and vlc decode the vectors and coeff's.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// Get the first skip run from the stream for P slices.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_NOVLC_READ;
		bitsUsedSoFar += numBits;
		/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RUNOUTOFBITS_READ;
	}//end if !I_Slice...

	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		/// --------------- Decode the macroblock header from the stream ----------------------

		if (_mb_skip_run && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			pMb->_skip = 1;
			_mb_skip_run--;

			/// Skip implies a P_Skip macroblock type as Inter_16x16.
			pMb->_intraFlag = 0;
			pMb->_mb_type = MacroBlockH264::Inter_16x16;
			pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;
			/// Skip implies a single 16x16 (0,0) motion vector difference.
			pMb->_mvdX[MacroBlockH264::_16x16] = 0;
			pMb->_mvdY[MacroBlockH264::_16x16] = 0;
			/// Set the motion vector to the predicted value.
			if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
			{
				/// Force to zero.
				pMb->_mvX[MacroBlockH264::_16x16] = 0;
				pMb->_mvY[MacroBlockH264::_16x16] = 0;
			}//end if SkippedZeroMotionPredCondition...
			else
				pMb->GetMbMotionMedianPred(pMb, &(pMb->_mvX[MacroBlockH264::_16x16]), &(pMb->_mvY[MacroBlockH264::_16x16]));
			pMb->_coded_blk_pattern = 0;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _mb_skip_run...
		else
		{
			/// Macroblock not skipped and header must be extracted.
			pMb->_skip = 0;

			/// Macroblock type.
			_pMb[mb]._mb_type = _pMbTypeVlcDec->Decode(bsr);
			numBits = _pMbTypeVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
			/// Unpack _intraFlag and _mbPartPredMode from the decoded _mb_type.
			_pMb[mb].UnpackMbType(&(_pMb[mb]), _slice._type);

			/// Intra requires lum and chr prediction modes, Inter requires reference 
			/// index lists and motion vector diff values.
			if (!_pMb[mb]._intraFlag)	///< Inter	(most common option)
			{
				int numOfVecs = 1;
				// TODO: Implement other partition modes.
				if (_pMb[mb]._mbPartPredMode == MacroBlockH264::Inter_16x16)
					numOfVecs = 1;
				else
					goto H264V2_NOMODE_READ;
				for (int vec = 0; vec < numOfVecs; vec++)
				{
					/// Get the motion vector differences for this macroblock.
					_pMb[mb]._mvdX[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;

					_pMb[mb]._mvdY[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RUNOUTOFBITS_READ;

					/// Get the prediction vector from the neighbourhood.
					int predX, predY;
					_pMb[mb].GetMbMotionMedianPred(&(_pMb[mb]), &predX, &predY);
					_pMb[mb]._mvX[vec] = predX + _pMb[mb]._mvdX[vec];
					_pMb[mb]._mvY[vec] = predY + _pMb[mb]._mvdY[vec];
				}//end for vec...
			}//end if !_interFlag...
			else											/// Intra
			{
				// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

				/// Get chr prediction mode.
				_pMb[mb]._intraChrPredMode = _pMbIChrPredModeVlcDec->Decode(bsr);
				numBits = _pMbIChrPredModeVlcDec->GetNumDecodedBits();
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end else...

			/// If not Intra_16x16 mode then _coded_blk_pattern must be extracted.
			if ((_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!_pMb[mb]._intraFlag))
			{
				/// Block coded pattern.
				int isInter = 1;
				if (_pMb[mb]._intraFlag) isInter = 0;
				numBits = _pBlkPattVlcDec->Decode2(bsr, &(_pMb[mb]._coded_blk_pattern), &isInter);
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if !Intra_16x16...

		}//end else not skipped...

		/// Disassemble the bit pattern to determine which blocks are to be decoded.
		_pMb[mb].GetCodedBlockPattern(&(_pMb[mb]));

		/// For Inter modes and non-Intra_16x16 modes, delta qp is read only if there is at least one block 
		/// that has coeffs. The all zero coeff condition still requires the pattern to be decoded such that 
		/// zeros are loaded into the blocks.
		_pMb[mb]._mb_qp_delta = 0;	///< Default value required.
		if ((_pMb[mb]._coded_blk_pattern > 0) || (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16)))
		{
			/// Delta QP.
			_pMb[mb]._mb_qp_delta = _pDeltaQPVlcDec->Decode(bsr);
			numBits = _pDeltaQPVlcDec->GetNumDecodedBits();
			if (numBits == 0)
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if _coded_blk_pattern...

		int prevMbIdx = _pMb[mb]._mbIndex - 1;
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (_pMb[mb]._slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				_pMb[mb]._mbQP = _pMb[prevMbIdx]._mbQP + _pMb[mb]._mb_qp_delta;
			else
				_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;
		}//end if prevMbIdx...
		else
			_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;

		/// ------------------- Get the macroblock coeffs from the coded stream ---------------------
		int dcSkip = 0;
		int startBlk = 1;
		if (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16))
		{
			startBlk = 0;	///< Change starting block to include block num = -1;
			dcSkip = 1;
		}//end if Intra_16x16...
		/// For Lum blocks that are Inter coded and not Intra_16x16 coded the DC coeff is not skipped.
		for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
			_pMb[mb]._blkParam[i].dcSkipFlag = dcSkip;

		for (i = startBlk; i < MBH264_NUM_BLKS; i++)
		{
			/// Simplify the block reference.
			BlockH264* pBlk = _pMb[mb]._blkParam[i].pBlk;

			if (pBlk->IsCoded())
			{
				/// Choose the appropriate dimension CAVLC codec.
				IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
				if ((pBlk->GetHeight() == 4) && (pBlk->GetWidth() == 4))
					pCAVLC = _pCAVLC4x4;

				/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
				/// MB decodings in decoding order have already set the num of neighbourhood coeffs.
				int neighCoeffs = 0;
				if (_pMb[mb]._blkParam[i].neighbourIndicator)
				{
					if (_pMb[mb]._blkParam[i].neighbourIndicator > 0)
						neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pBlk);
					else	///< Negative values for neighbourIndicator imply pass through.
						neighCoeffs = _pMb[mb]._blkParam[i].neighbourIndicator;
				}//end if neighbourIndicator...
				pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
				pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, _pMb[mb]._blkParam[i].dcSkipFlag);

				numBits = pBlk->RleDecode(pCAVLC, bsr);					///< Vlc decode from the stream.
				if (numBits <= 0)	///< Vlc codec errors are detected from a negative return value.
				{
					if (numBits == -2)
						goto H264V2_RUNOUTOFBITS_READ;
					goto H264V2_NOVLC_READ;
				}//end if numBits...
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if IsCoded()...
			else
			{
				pBlk->SetNumCoeffs(0);	///< For future use.
				pBlk->Zero();
			}//end else...
		}//end for i...

		/// If end of skipped macroblocks then get the next skip run from the stream.
		if (!_mb_skip_run && !pMb->_skip && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All) && (mb != (len - 1)))
		{
			_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if !_mb_skip_run...

	}//end for mb...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Mode not supported";
	*bitsUsed = bitsUsedSoFar;
	return(3);
}//end ReadSliceDataLayer.

/** Write the macroblock layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes one non-skipped macroblock encoding.
Each write checks if a bit overflow will occur before writing. The check
is sufficiently frequent to warrant an early exit GOTO statement. If the
input stream param is NULL then this method is used to count the bits only.
@param bsw					: Stream to write into.
@param pMb					: Macroblock to encode.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;
	int dcSkip = 0;
	int startBlk = 1;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitCount = _pMbTypeVlcEnc->Encode(pMb->_mb_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_VLCERROR_WRITE_MB;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_RUNOUTOFBITS_WRITE_MB;
	if (bsw)
		bsw->Write(bitCount, _pMbTypeVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

		}//end for vec...
	}//end if !_intraFlag...
	else											/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitCount = _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pMbIChrPredModeVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitCount = _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pBlkPattVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitCount = _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pDeltaQPVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitCount = (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, bsw);
			if (bitCount <= 0)
			{
				if (bitCount == -2)
					goto H264V2_RUNOUTOFBITS_WRITE_MB;
				goto H264V2_VLCERROR_WRITE_MB;
			}//end if bitCount...
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			bitsUsedSoFar += bitCount;
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE_MB:
	/// Error info has contents loaded from outside of this method therefore concat is required.
	//strcat(_errorInfo, " H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture");
	//_errorStr = _errorInfo;
	_errorStr = "H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE_MB:
	_errorStr = "H264V2:[WriteMacroBlockLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteMacroBlockLayer.

/** Count the bits required to encode the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding. NB: No errors are checked.
@param pMb					: Macroblock to encode.
@return							: Total bit count.
*/
int H264v2Codec::MacroBlockLayerBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitsUsedSoFar = _pMbTypeVlcEnc->Encode(pMb->_mb_type);

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
		}//end for vec...
	}//end if !_intraFlag...
	else									/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitsUsedSoFar += _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitsUsedSoFar += _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitsUsedSoFar += _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerBitCounter.

/** Count the bits required to encode the coeffs at the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding excluding the headers. NB: No errors
are checked.
@param pMb	: Macroblock to encode.
@return			: Total bit count.
*/
int H264v2Codec::MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Ignore
  /// the header.

	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...

	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and accumulate the bit count. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerCoeffBitCounter.

/** Read the macroblock layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadMacroBlockLayer.

/** Apply the in-loop edge filter.
Used in both the encoder and decoder to remove blocking artefacts on the 4x4 boundary
edges. It is applied macroblock by macroblock in raster scan order to the reference
images of both the Lum and Chr components.
@return	:	none.
*/
void H264v2Codec::ApplyLoopFilter(void)
{
	int mb, i, j;
	short** lumRef = _RefLum->Get2DSrcPtr();	///< Image space to operate on.
	short** cbRef = _RefCb->Get2DSrcPtr();
	short** crRef = _RefCr->Get2DSrcPtr();

	for (mb = 0; mb < _mbLength; mb++)
	{
		MacroBlockH264* pMb = &(_pMb[mb]);
		MacroBlockH264* aboveMb = _pMb[mb]._aboveMb;
		MacroBlockH264* leftMb = _pMb[mb]._leftMb;

		/// All macroblock boundaries that have intra neighbours use
		/// boundary strength = {3, 4}. Vertical filtering first.

		///---------------- Vertical Edges --------------------------------------
		if (leftMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || leftMb->_intraFlag)	///< Left intra macroblock boundary (bS = 4).
			{
				for (i = 0; i < 16; i += 4)
					VerticalFilter(pMb, lumRef, 1, i, 0, 4, 4);
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, 0, 4, 4);
					VerticalFilter(pMb, crRef, 0, i, 0, 4, 4);
				}//end for i...
			}//end if _intraFlag...
			else																	///< Left inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 vector is used
				// per macroblock and from the same single reference. Boundary 4x4 blocks 
		// are compared with the neighbouring macroblock motion vectors.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - leftMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - leftMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (i = 0; i < 4; i++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[i][0].GetNumCoeffs() || pMb->_lumBlk[i][0]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, 0, 4, bS);	///< At (row = 4*i, col = 0) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						VerticalFilter(pMb, cbRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
						VerticalFilter(pMb, crRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
					}//end if bS...
				}//end for i...

			}//end else...
		}//end if leftMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (j = 4; j < 16; j += 4)
				for (i = 0; i < 16; i += 4)	///< All rows first for each col.
					VerticalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (j = 4; j < 8; j += 4)
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, j, 4, 3);
					VerticalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for j & i...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (j = 1; j < 4; j++)
				for (i = 0; i < 4; i++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (j == 2)
						{
							VerticalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
							VerticalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
						}//end if j...
					}//end if bS...

				}//end for j & i...
		}//end else...

		///---------------- Horizontal Edges -------------------------------------
		if (aboveMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || aboveMb->_intraFlag)	///< Above intra macroblock boundary. (bS = 4)
			{
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, 0, j, 4, 4);
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, 0, j, 4, 4);
					HorizontalFilter(pMb, crRef, 0, 0, j, 4, 4);
				}//end for j...
			}//end if _intraFlag...
			else																	///< Above inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 motion vector is used
				// per macroblock and from the same single reference.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - aboveMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - aboveMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (j = 0; j < 4; j++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[0][j].GetNumCoeffs() || pMb->_lumBlk[0][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						HorizontalFilter(pMb, lumRef, 1, 0, j << 2, 4, bS);	///< At (row = 0, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						HorizontalFilter(pMb, cbRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
						HorizontalFilter(pMb, crRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
					}//end if bS...
				}//end for j...

			}//end else...
		}//end aboveMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (i = 4; i < 16; i += 4)
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (i = 4; i < 8; i += 4)
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, i, j, 4, 3);
					HorizontalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for i & j...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (i = 1; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						HorizontalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (i == 2)
						{
							HorizontalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
							HorizontalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
						}//end if i...
					}//end if bS...

				}//end for i & j...
		}//end else...

	}//end for mb...

}//end ApplyLoopFilter.

/** Apply the in-loop deblocking filter to vertical block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one column with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations down the col from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + pMb->_leftMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_leftMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY + i][offX - 1] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY + i][offX] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX - 2] = (short)(p1 + delta);		                ///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX + 1] = (short)(q1 + delta);		                ///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be colOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX - 1] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY + i][offX - 2] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY + i][offX - 3] = (short)(((2 * (int)(img[offY + i][offX - 4])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX - 1] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + i][offX + 1] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + i][offX + 2] = (short)(((2 * (int)(img[offY + i][offX + 3])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end VerticalFilter.

/** Apply the in-loop deblocking filter to horizontal block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one row with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations along the row from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + pMb->_aboveMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_aboveMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY - 1][offX + i] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY][offX + i] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY - 2][offX + i] = (short)(p1 + delta);			///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + 1][offX + i] = (short)(q1 + delta);			///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be rowOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY - 1][offX + i] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY - 2][offX + i] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY - 3][offX + i] = (short)(((2 * (int)(img[offY - 4][offX + i])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY - 1][offX + i] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY][offX + i] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + 1][offX + i] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + 2][offX + i] = (short)(((2 * (int)(img[offY + 3][offX + i])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY][offX + i] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end HorizontalFilter.

/** Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		short*			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i]);	///< Short cuts.
		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);

		/// Transform without scaling or quant.
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][0]
		*pDcLumBlk++ = pLumBlk->GetDC(); ///< Set the Lum DC block from the DC term of this block and scale it without rounding.
		(pLumBlk++)->SetDC(0); ///< Required to ensure the feedback loop operates properly.

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][1]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][2]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][3]
		*pDcLumBlk = pLumBlk->GetDC();
		pLumBlk->SetDC(0);

		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][3]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][2]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][1]
		pLumBlk->Quantise(_pF4x4TLum);			///< [i][0]
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantIntra16x16MBlk.

/** Transform and Quantise an Intra_16x16 macroblock to below a max distortion criterion.
This overload method decrements the mb QP value from its existing value until the mb distortion
drops below the specified Dmax value. It returns the distortion at the final value of QP that
meets the criterion and places the decoded mb values in the temp blks. The final inverse decoded
blks are stored in the tmp blks.
@param pMb	  : Macroblock to transform.
@param Dmax   : Target max distortion criterion.
@param minQP  : Lowest QP value allowed.
@return			  : Lum distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int qp = pMb->_mbQP;
	int distortion = 0;

	///------------ Lum in raster scan order--------------------------

	  /// Transform without quant to extract the DC term. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);

			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);   ///< DCT.
			*pDcLumBlk++ = pb->GetDC();         ///< Set DC blk
			pb->SetDC(0);                       ///< Clear DC term in AC blk.
		}//end for i & j...

		/// Transform the DC blocks.
	_pFDC4x4T->SetMode(IForwardTransform::TransformOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	/// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);
		_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			}//end for i & j...

			/// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

		/// For QP = H264V2_MAX_QP it is likely that all coeffs are zeros. Find the QP value 
		/// that results in at least 1 non-zero coeff.
	//    if(qp == H264V2_MAX_QP)
	//      qp = GetQPtoNonZeroCoeff(pMb, minQP);

		/// Inverse quant and inverse transform the DC blks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

		/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
		distortion = 0;
		short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to DC blk.
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
				pb->InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
				pb->SetDC(*pDcLumBlkTmp++);       ///< Load the DC term from the DC blk.

				_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
				pb->InverseTransform(_pI4x4TLum); ///< Inverse transform.

				/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

		/// Update mb QP.
		pMb->_mbQP = qp;
		/// New qp.
		qp -= 4; //MbStepSize[qp];
		if (qp < minQP) qp = minQP;

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the main lum AC and DC blks.
	_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
		}//end for i & j...
	_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	///----------- Chr in raster scan order --------------------------

	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...

	  /// Restore state.
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	pMb->_mbEncQP = pMb->_mbQP;

	return(distortion);
}//end TransAndQuantIntra16x16MBlk.

/** Code refactoring for TransAndQuantIntra16x16MBlk() method.
Get the mb QP value such that there is at least one non-zero DCT coeff.
@param pMb	  : Macroblock to transform.
@return       : QP value for non-zero coeffs.
*/
int H264v2Codec::GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP)
{
	int i, j;
	int qp = H264V2_MAX_QP;

	/// Are all coeffs zeros?
	int isZero = pMb->_lumDcBlkTmp.IsZero2();
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			isZero &= pMb->_lumBlkTmp[i][j].IsZero2();
	if (isZero)
	{
		/// Re-quant at QP = 1.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, 1);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);

		/// Find the blk and position of the peak peak value.
		BlockH264*  pPeakBlk = &(pMb->_lumDcBlkTmp);
		short*      pB = pPeakBlk->GetBlk();
		int         peakPos = 0;
		short       peakVal = abs(pB[0]);

		for (i = 1; i < 16; i++) ///< DC blk.
		{
			if (abs(pB[i]) > peakVal)
			{
				peakPos = i;
				peakVal = abs(pB[i]);
			}//end if pB[]...
		}//end for i...

		for (i = 0; i < 4; i++)  /// AC blks.
			for (j = 0; j < 4; j++)
			{
				pB = pMb->_lumBlkTmp[i][j].GetBlk();
				for (int k = 0; k < 16; k++)
				{
					if (abs(pB[k]) > peakVal)
					{
						peakPos = k;
						peakVal = abs(pB[k]);
						pPeakBlk = &(pMb->_lumBlkTmp[i][j]);
					}//end if abs(pB[])...
				}//end for k...
			}//end for i & j...

		  /// Get the pre-quant value from the main blks in the position required.
		short val = (pPeakBlk->GetBlk())[peakPos];
		IForwardTransform* pQuantiser = _pF4x4TLum;
		if (pPeakBlk->IsDc())
			pQuantiser = _pFDC4x4T;

		/// Quantise this single peak value until it is non-zero.
		qp = H264V2_MAX_QP - 1;
		while ((qp > minQP) && (pQuantiser->QuantiseValue(val, peakPos, qp) == 0))
		{
			qp -= MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end while qp...

		/// Re-load and quantise the whole mb at this new QP value.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			  /// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

	}//end if isZero...

	return(qp);
}//end SetQPtoNonZeroCoeff.

/** Transform and Quantise an Intra_16x16 macroblock with Inverse.
This method provides a speed improvement for macroblock processing and code refactoring. The
inverse transform and distortion measurment is included to the temp blks.
@param pMb	  : Macroblock to transform.
@param withD  : Include distortion calculation.
@return			  : distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD)
{
	int i, j;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	int distortion = 0;

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method. The DC blocks are in the TransformAndQuant mode.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);

	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
  /// Copy the coeffs to the temp blks and do the inverse process.

  ///------------ Lum in raster scan order--------------------------

	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			if (withD)
				pMb->_lumBlk[i][j].Copy(_tmpBlk[i][j].GetBlk());

			_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
			pMb->_lumBlk[i][j].ForwardTransform(_pF4x4TLum);  ///< DCT.
			pDcLumBlk[i * 4 + j] = pMb->_lumBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_lumBlk[i][j].SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TLum->SetMode(IForwardTransform::QuantOnly); ///< Scale and quant.
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);

		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Copy the Lum blks into the temp Lum blks for inverse transform + quant processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

	/// Inverse quant and inverse transform the temp DC blks.
	pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

	/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
	short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to temp DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
			pMb->_lumBlkTmp[i][j].InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
			pMb->_lumBlkTmp[i][j].SetDC(pDcLumBlkTmp[4 * i + j]); ///< Load the DC term from the DC blk.

			_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
			pMb->_lumBlkTmp[i][j].InverseTransform(_pI4x4TLum); ///< Inverse transform.

			/// Total square diff with the input store.
			if (withD)
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
		}//end for i & j...

  /// Region of interest multiplier application to the whole mb.
  distortion = ROIDistortion(pMb->_mbIndex, distortion);

  ///----------- Chr in raster scan order --------------------------

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pMb->_cbBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCbBlk[i * 2 + j] = pMb->_cbBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_cbBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			/// Cr
			pMb->_crBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCrBlk[i * 2 + j] = pMb->_crBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_crBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pMb->_cbBlk[i][j].Quantise(_pF4x4TChr);         ///< Scale and quant.
			pMb->_crBlk[i][j].Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pMb->_cbBlkTmp[i][j].InverseQuantise(_pI4x4TChr); ///< Inverse scale and quant.
			pMb->_cbBlkTmp[i][j].SetDC(pDcCbBlkTmp[2 * i + j]); ///< Load the DC term from the DC blk.
			pMb->_crBlkTmp[i][j].InverseQuantise(_pI4x4TChr);
			pMb->_crBlkTmp[i][j].SetDC(pDcCrBlkTmp[2 * i + j]);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pMb->_cbBlkTmp[i][j].InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pMb->_crBlkTmp[i][j].InverseTransform(_pI4x4TChr);
		}//end for i & j...

	return(distortion);
}//end TransAndQuantIntra16x16MBlkWithInv.

/** Transform and Quantise an Intra_16x16 mode block.
Code refactoring method to transform the block and store the DC coeff before quantisation. The
transform must have the quantisation parameter preset before calling this method.
@param pTQ					: Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to store the DC coeff.
@return							: none.
*/
void H264v2Codec::TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IForwardTransform::TransformOnly);
	pBlk->ForwardTransform(pTQ);
	*pDcBlkCoeff = pBlk->GetDC();	///< Set the DC block from the DC term of this block.
	pBlk->SetDC(0);								///< Required to ensure the feedback loop operates properly.
	pTQ->SetMode(IForwardTransform::QuantOnly);
	pBlk->Quantise(pTQ);
}//end TransAndQuantIntra16x16ModeBlk.

/** Inverse Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks to temp blks.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, 0, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlk.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		short*			pDcLumBlk;
		BlockH264*	pLumBlk;

		/// Unroll the inner loop.

		if (tmpBlkFlag)
		{
			pDcLumBlk = &((pMb->_lumDcBlkTmp.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlkTmp[i][0]);
		}//end if tmpBlkFlag...
		else
		{
			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlk[i][0]);
		}//end else...

		/// Inverse scale and quant.
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][2]
		pLumBlk->InverseQuantise(_pI4x4TLum);			///< [i][3]
		_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform without scaling or quant.
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);

		pLumBlk->SetDC(*pDcLumBlk--);						///< Load the DC term from the DC block.
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][3]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][2]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][1]

		pLumBlk->SetDC(*pDcLumBlk);
		pLumBlk->InverseTransform(_pI4x4TLum);			///< [i][0]

		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantIntra16x16MBlk.

/** Inverse Quantise and Transform an Intra_16x16 mode block.
Code refactoring method to inverse quantise the block and set the DC coeff before the inverse
transform. The inverse transform must have the quantisation parameter preset before calling
this method.
@param pTQ					: Inverse Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to get the DC coeff.
@return							: none.
*/
void H264v2Codec::InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IInverseTransform::QuantOnly);
	pBlk->InverseQuantise(pTQ);
	pBlk->SetDC(*pDcBlkCoeff);	///< Set the DC coeff for this block from the DC block.
	pTQ->SetMode(IInverseTransform::TransformOnly);
	pBlk->InverseTransform(pTQ);
}//end InvTransAndQuantIntra16x16ModeBlk.

/** Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the chr 4x4 AC blocks in this method. The lum and DC blocks are in the 
  /// TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetMode(IForwardTransform::TransformAndQuant);
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each chr block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);	///< Short cuts.

		/// Transform Lum with scaling and quant.
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][0]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][1]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][2]
		pLumBlk->ForwardTransform(_pF4x4TLum);			///< [i][3]

	/// For chr, split the transform and quant processes. 
		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant chr.
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantInter16x16MBlk.

/** Transform and Quantise an Inter_16x16 macroblock with a Dmax criterion.
This method provides a speed improvement for macroblock processing and code refactoring. The
QP value is decremented until the mb Lum distortion is below Dmax. The quatised coeff are stored
in the _lumBlk[][], etc. and the inverse reconstructed pels are stored in the _lumBlkTmp[][], etc.
@param pMb	  : Macroblock to transform.
@param Dmax   : Max distortion for this mb.
@param minQP  : Lower limit for the QP descent.
@return			  : Distortion for the mb.
*/
int H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int distortion = 0;
	int qp = pMb->_mbQP;
	int eqp = pMb->_mbEncQP;
	if (eqp > (H264V2_MAX_QP + 16))  ///< Only consider lum coeffs.
		eqp = H264V2_MAX_QP + 16;

	/// ----------------------------- Lum -----------------------------------------------------------
	/// Transform without quant and store. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the motion pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);
		}//end for i & j...

	  /// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	  /// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_0_0, MBH264_LUM_3_3);

		/// Quant only for the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		/// Invese quant and transform.
		_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);

		/// Forward quant and inverse quant and transform. Accumulate distortion.
		distortion = 0;
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				pb->ForwardTransform(_pF4x4TLum); ///< Forward quant.
				/// For extended EncQP range [52..67], zero coeffs.
				if (eqp > H264V2_MAX_QP)
					pb->Zero(16 - (eqp - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);

				pb->InverseTransform(_pI4x4TLum);	///< Inverse scale, quant and transform.
			/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

    /// Update mb QP.
		pMb->_mbQP = qp;
		pMb->_mbEncQP = eqp;
		/// New qp.
		if (eqp > H264V2_MAX_QP)
		{
			eqp -= 4;
			if (eqp < H264V2_MAX_QP) eqp = H264V2_MAX_QP;
		}//end if eqp...
		else
		{
			qp -= 4; //MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end else...

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the lum blks.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			/// Zero coeffs for extended EncQP range.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
				pMb->_lumBlk[i][j].Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
		}//end for i & j...

	  /// ----------------------------- Chr -----------------------------------------------------------
	  /// Chr is processed after the QP value for this block has been determined by the Lum process.
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);

			/// Follow the lum extended QP range on the Chr AC coeffs.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
			{
				pCb->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
				pCr->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
			}//end if _mbEncQP...
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...


	return(distortion);
}//end TransAndQuantInter16x16MBlk.

/** Inverse Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to inverse transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pLumBlk;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks, excluding Lum DC blk, to temp blks.
		MacroBlockH264::CopyBlksToTmpBlksCoeffOnly(pMb, 1, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Lum & Chr components.
		pLumBlk = &(pMb->_lumBlkTmp[0][0]);
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pLumBlk = &(pMb->_lumBlk[0][0]);
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		/// Unroll the inner loop.

		/// Inverse scale, quant and transform Lum.
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][2]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][3]

	/// Inverse scale and quant first for Chr.
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform after scaling and quant.
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantInter16x16MBlk.

/** Get Intra Lum prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref lum img and write it to the pred parameter. Used by the encoder. Return the
intra_16x16 prediction mode.
@param pMb				: Macroblock to predict.
@param in					: Lum input image.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred)
{
	int i, j;
	int a, b, c;	///< Plane mode intermediates.
	int predDC;	///< Other mode intermediates.
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_16x16_DC;

	short**	in2D = in->Get2DSrcPtr();
	int			iOffX = in->GetOriginX();
	int			iOffY = in->GetOriginY();
	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Plane mode preparation --------------------------------------
		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
			V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
		}//end for i...
		b = (5 * H + 32) >> 6;
		c = (5 * V + 32) >> 6;
		a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_16x16_Plane] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], H264V2_CLIP255((a + b*(x - 7) + c*(y - 7) + 16) >> 5));
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 3; i++)	///< Total of 3 modes. Plane mode excluded.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY + i][rOffX - 1];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Horiz;	///< MacroBlockH264::Intra_16x16_Horiz = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Horiz])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY - 1][rOffX + i];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Vert])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Lum value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		pred->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
		pred->Fill(predDC);
		break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
	}//end Horiz block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra16x16LumPredAndMode.

/** Get Intra Lum prediction.
Apply the prediction mode specified to predict from the ref lum img and write it to the pred
parameter. Used by the decoder.
@param pMb				: Macroblock to predict.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@param predMode		: Mode to apply.
@return						: 1 = success, 0 = failure.
*/
int H264v2Codec::GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode)
{
	int i, j;

	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Fill the prediction block with the appropriate mode prediction.
	switch (predMode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		if (pMb->_aboveMb != NULL)	///< Vert prediction only cares about the macroblock above.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
		}//end if aboveMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		if (pMb->_leftMb != NULL)	///< Horiz prediction only cares about the macroblock to the left.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
		}//end if leftMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
	{
		bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);
		bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);
		bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);

		int predDC = 0;
		if (aboveAndLeft)
		{
			for (i = 0; i < 16; i++)
				predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
			predDC = (predDC + 16) >> 5;
		}//end if aboveAndLeft...
		else if (leftOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY + i][rOffX - 1];
			predDC = (predDC + 8) >> 4;
		}//end else if leftOnly...
		else if (aboveOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY - 1][rOffX + i];
			predDC = (predDC + 8) >> 4;
		}//end else if aboveOnly...
		else
		{
			predDC = 128;	///< Half the max value.
		}//end else...

		pred->Fill(predDC);
	}//end DC block...
	break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);

		if (all)	///< All the neighbouring macroblocks must be available for prediction.
		{
			int		H = 0;
			int		V = 0;
			for (i = 0; i < 8; i++)
			{
				H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
				V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
			}//end for i...
			int b = (5 * H + 32) >> 6;
			int c = (5 * V + 32) >> 6;
			int a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
		}//end if all...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	}//end switch predMode...

	return(1);
}//end GetIntra16x16LumPred.

/** Get Intra Lum DC prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int dirCnt = 0;
	int predValue = 0;

	short** img = lum->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offLumX;
		offY = pMb->_aboveMb->_offLumY + 15;
		for (i = 0; i < 16; i++)
			predValue += img[offY][offX + i];
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offLumX + 15;
		offY = pMb->_leftMb->_offLumY;
		for (i = 0; i < 16; i++)
			predValue += img[offY + i][offX];
	}//end if _leftMb...

	/// Set the accumulated DC prediction value.
	if (dirCnt == 2)
		predValue = (predValue + 16) >> 5;
	else if (dirCnt == 1)
		predValue = (predValue + 8) >> 4;
	else
		predValue = 128;	///< Half max Lum value.

	pred->Fill(predValue);

}//end GetIntra16x16LumDCPred.

/** Get Intra Lum Plane prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction. The H.264 std does not specify
this last case for Plane pred.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = lum->Get2DSrcPtr();
		int			iOffX = lum->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = lum->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 8 + i] - (int)img2D[iOffY - 1][iOffX + 6 - i]);
			V += (i + 1)*((int)img2D[iOffY + 8 + i][iOffX - 1] - (int)img2D[iOffY + 6 - i][iOffX - 1]);
		}//end for i...
		int b = (5 * H + 32) >> 6;
		int c = (5 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 15][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 15]) << 4;

		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
			{
				short x = (short)((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra16x16LumPlanePred.

/** Get Intra Vertical prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prediction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i;
	MacroBlockH264* amb = pMb->_aboveMb;

	if (amb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last row of the macroblock above.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = amb->_offLumX;
			iOffY = amb->_offLumY + (img->GetHeight() - 1);
		}//end if lumFlag...
		else
		{
			iOffX = amb->_offChrX;
			iOffY = amb->_offChrY + (img->GetHeight() - 1);
		}//end else...
		short* ps = &(img2D[iOffY][iOffX]);
		for (i = 0; i < height; i++)	///< Rows.
			memcpy((void *)(&(pred2D[offY + i][offX])), (const void *)ps, byteLen);
		return(1);
	}//end if amb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Macroblock above does not exist.
}//end GetIntraVertPred.

/** Get Intra Horizontal prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prodiction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i, j;
	MacroBlockH264* lmb = pMb->_leftMb;

	if (lmb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last col of the macroblock to the left.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = lmb->_offLumX + (img->GetWidth() - 1);
			iOffY = lmb->_offLumY;
		}//end if lumFlag...
		else
		{
			iOffX = lmb->_offChrX + (img->GetWidth() - 1);
			iOffY = lmb->_offChrY;
		}//end else...
		for (i = 0; i < height; i++)	///< Rows.
		{
			short* pd = &(pred2D[offY + i][offX]);
			short  x = img2D[iOffY + i][iOffX];
			for (j = 0; j < width; j++)
				*pd++ = x;
		}//end for i...
		return(1);
	}//end if lmb...

	/// Safety precaution not defined in H.264 standard. If the left macroblock
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Left macroblock does not exist.
}//end GetIntraHorizPred.

/** Get Intra Chr prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref chr img and write it to the pred parameter. Used by the encoder. Return the
intra_8x8 prediction mode.
@param pMb				: Macroblock to predict.
@param cb					: Cb Chr input image.
@param cr					: Cr Chr input image.
@param refCb			: Reference chr Cb img to predict from.
@param refCr			: Reference chr Cr img to predict from.
@param predCb			: 8x8 Cb overlay to write result to.
@param predCr			: 8x8 Cr overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
	OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr,
	OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr)
{
	int i, j;
	int aCb, bCb, cCb, aCr, bCr, cCr;	///< Plane mode intermediates.
	int predCbDC[4] = { 0, 0, 0, 0 };	///< DC mode intermediates.
	int predCrDC[4] = { 0, 0, 0, 0 };
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_Chr_DC;

	short**	inCb2D = cb->Get2DSrcPtr();
	short**	inCr2D = cr->Get2DSrcPtr();
	int			iOffX = cb->GetOriginX();	///< Assume Cb and Cr have the same offsets.
	int			iOffY = cb->GetOriginY();
	short**	refCb2D = refCb->Get2DSrcPtr();
	short**	refCr2D = refCr->Get2DSrcPtr();
	int			rOffX = refCb->GetOriginX();
	int			rOffY = refCb->GetOriginY();
	short**	predCb2D = predCb->Get2DSrcPtr();
	short**	predCr2D = predCr->Get2DSrcPtr();
	int			pOffX = predCb->GetOriginX();
	int			pOffY = predCr->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Plane mode preparation --------------------------------------
		int		HCb = 0;
		int		VCb = 0;
		int		HCr = 0;
		int		VCr = 0;
		for (i = 0; i < 4; i++)
		{
			HCb += (i + 1)*((int)refCb2D[rOffY - 1][rOffX + 4 + i] - (int)refCb2D[rOffY - 1][rOffX + 2 - i]);
			VCb += (i + 1)*((int)refCb2D[rOffY + 4 + i][rOffX - 1] - (int)refCb2D[rOffY + 2 - i][rOffX - 1]);
			HCr += (i + 1)*((int)refCr2D[rOffY - 1][rOffX + 4 + i] - (int)refCr2D[rOffY - 1][rOffX + 2 - i]);
			VCr += (i + 1)*((int)refCr2D[rOffY + 4 + i][rOffX - 1] - (int)refCr2D[rOffY + 2 - i][rOffX - 1]);
		}//end for i...
		bCb = (34 * HCb + 32) >> 6;
		cCb = (34 * VCb + 32) >> 6;
		aCb = ((int)refCb2D[rOffY + 7][rOffX - 1] + (int)refCb2D[rOffY - 1][rOffX + 7]) << 4;
		bCr = (34 * HCr + 32) >> 6;
		cCr = (34 * VCr + 32) >> 6;
		aCr = ((int)refCr2D[rOffY + 7][rOffX - 1] + (int)refCr2D[rOffY - 1][rOffX + 7]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_Chr_Plane] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCb + bCb*(x - 3) + cCb*(y - 3) + 16) >> 5))) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCr + bCr*(x - 3) + cCr*(y - 3) + 16) >> 5))));
		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 3; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY + i][rOffX - 1];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];

			predCrDC[0] += (int)refCr2D[rOffY + i][rOffX - 1];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[1] = predCbDC[0];
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = predCbDC[2];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[1] = predCrDC[0];
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = predCrDC[2];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (y > 3)
				partition = 2;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Horiz] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Horiz;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY - 1][rOffX + i];
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];

			predCrDC[0] += (int)refCr2D[rOffY - 1][rOffX + i];
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[2] = predCbDC[0];
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[3] = predCbDC[1];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[2] = predCrDC[0];
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[3] = predCrDC[1];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (x > 3)
				partition = 1;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));

		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Vert] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Vert;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Chr value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		predCb->Fill(128);
		predCr->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_Chr_DC:
	{
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = predCbDC[0];
				predCb2D[pOffY + i][pOffX + 4 + j] = predCbDC[1];
				predCb2D[pOffY + 4 + i][pOffX + j] = predCbDC[2];
				predCb2D[pOffY + 4 + i][pOffX + 4 + j] = predCbDC[3];

				predCr2D[pOffY + i][pOffX + j] = predCrDC[0];
				predCr2D[pOffY + i][pOffX + 4 + j] = predCrDC[1];
				predCr2D[pOffY + 4 + i][pOffX + j] = predCrDC[2];
				predCr2D[pOffY + 4 + i][pOffX + 4 + j] = predCrDC[3];
			}//end for i & j...
	}//end DC block...
	break;
	case MacroBlockH264::Intra_Chr_Horiz:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY + i][rOffX - 1];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY + i][rOffX - 1];
			}//end i & j...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_Chr_Vert:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY - 1][rOffX + j];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY - 1][rOffX + j];
			}//end for i & j...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_Chr_Plane:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCb + bCb*(j - 3) + cCb*(i - 3) + 16) >> 5);
				predCr2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCr + bCr*(j - 3) + cCr*(i - 3) + 16) >> 5);
			}//end for i & j...
	}//end Plane block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra8x8ChrPredAndMode.

/** Get Intra Chr DC prediction.
Predict from the parameter Chr img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use the
mid chr value (128) as the prediction. The H.264 std does not specify
this last case for DC pred.
@param pMb				: Macroblock to transform.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int predValue[4];
	int dirCnt = 0;
	int sum[4] = { 0, 0, 0, 0 };

	short** img = chr->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offChrX;
		offY = pMb->_aboveMb->_offChrY + 7;
		for (i = 0; i < 4; i++)
		{
			sum[0] += img[offY][offX + i];
			sum[1] += img[offY][offX + 4 + i];
		}//end for i...
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offChrX + 7;
		offY = pMb->_leftMb->_offChrY;
		for (i = 0; i < 4; i++)
		{
			sum[2] += img[offY + i][offX];
			sum[3] += img[offY + 4 + i][offX];
		}//end for i...
	}//end if _leftMb...

	/// Set the accumulated DC prediction values.
	if (dirCnt == 2)
	{
		predValue[0] = (sum[0] + sum[2] + 4) >> 3;
		predValue[1] = (sum[1] + 2) >> 2;
		predValue[2] = (sum[3] + 2) >> 2;
		predValue[3] = (sum[1] + sum[3] + 4) >> 3;
	}//end if dirCnt...
	else if (dirCnt == 1)
	{
		if (pMb->_leftMb == NULL)
		{
			predValue[0] = (sum[0] + 2) >> 2;
			predValue[1] = (sum[1] + 2) >> 2;
			predValue[2] = (sum[0] + 2) >> 2;
			predValue[3] = (sum[1] + 2) >> 2;
		}//end if !leftMb...
		else
		{
			predValue[0] = (sum[2] + 2) >> 2;
			predValue[1] = (sum[2] + 2) >> 2;
			predValue[2] = (sum[3] + 2) >> 2;
			predValue[3] = (sum[3] + 2) >> 2;
		}//end else...
	}//end else if dirCnt...
	else
	{
		/// Mid Chr value.
		predValue[0] = 128;
		predValue[1] = 128;
		predValue[2] = 128;
		predValue[3] = 128;
	}//end else...

	int xBase = pred->GetOriginX();
	int yBase = pred->GetOriginY();
	pred->SetOverlayDim(4, 4);
	for (int y = 0, i = 0; y < 2; y++)
		for (int x = 0; x < 2; x++, i++)
		{
			pred->SetOrigin(xBase + x * 4, yBase + y * 4);
			pred->Fill(predValue[i]);
		}//end for y & x...

	/// Put the block back into shape.
	pred->SetOverlayDim(8, 8);
	pred->SetOrigin(xBase, yBase);

}//end GetIntra8x8ChrDCPred.

/** Get Intra Chr Plane prediction.
Predict from the parameter Chr img and write it to the pred parameter. This
implementation if for YCbCr 4:2:0 chroma_format_idc = 1 only. If there are
no valid neighbours to make the prediction then use the mid chr value (128)
as the prediction. The H.264 std does not specify this last case for DC pred.
@param pMb				: Macroblock to predict.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = chr->Get2DSrcPtr();
		int			iOffX = chr->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = chr->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 4; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 4 + i] - (int)img2D[iOffY - 1][iOffX + 2 - i]);
			V += (i + 1)*((int)img2D[iOffY + 4 + i][iOffX - 1] - (int)img2D[iOffY + 2 - i][iOffX - 1]);
		}//end for i...
		int b = (34 * H + 32) >> 6;
		int c = (34 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 7][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 7]) << 4;

		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				short x = (short)((a + b*(j - 3) + c*(i - 3) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra8x8ChrPlanePred.

/*
-----------------------------------------------------------------------
  Private nested classes.
-----------------------------------------------------------------------
*/
/** Encode the image data for Intra IDR pictures.
Process all slices and their macroblocks in order. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
#ifdef H264V2_DUMP_MB_RD_DATA

		if ((mb > 66) && (_codec->_mbRDTablePos < 65)) ///< Collect data for 64 mbs starting in the 3rd mb row of the image.
		{
			/// Write the mb number in row 0.
			_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, 0, mb);

			int qp;
			for (qp = 1; qp < _codec->_mbRDTableLen; qp++)
			{
				_codec->_pMb[mb]._mbQP = qp;
				_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 2);  ///< D only.

				_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, qp, _codec->_pMb[mb]._distortion[qp]);
			}//end for qp...

			_codec->_mbRDTablePos++;  ///< Represents columns. 
		}//end if mb...

#endif /// H264V2_DUMP_MB_RD_DATA

		_codec->_pMb[mb]._mbQP = _codec->_slice._qp;
		_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 0);
	}//end for mb...

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplStdVer1::Encode.

/** Decode of the Intra macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		/// --------------------- Inverse Transform & Quantisation --------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			_codec->InverseTransAndQuantIntra16x16MBlk(pMb, 0);

		/// --------------------- Image Prediction and Storing -------------------------------------
		/// From the prediction mode settings, make the appropriate prediction macroblock and then
		/// add the inverse transformed and quantised values to it. Fill the image (difference) colour 
		/// components from all the non-DC 4x4 blks (i.e. Not blks = -1, 17, 18) of the macroblock blocks.

		/// Store blocks into ref img.
		MacroBlockH264::StoreBlks(pMb, _codec->_RefLum, lOffX, lOffY, _codec->_RefCb, _codec->_RefCr, cOffX, cOffY, 0);

		/// Predict the output from the previously decoded neighbour ref macroblocks.
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.

		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			_codec->GetIntra16x16LumDCPred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			_codec->GetIntra16x16LumPlanePred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		}//end switch _intra16x16PredMode...

		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);

		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraHorizPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraVertPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		}//end switch _intraChrPredMode...

		/// --------------------- Add the prediction -----------------------------------------------
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY);           ///< Align the Ref Lum img block with this macroblock.
		_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add pred to ref Lum and leave result in ref img.
		/// Cb.
		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
		/// Cr.
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

	}//end for mb...

	return(1);
}//end IntraImgPlaneDecoderImplStdVer1::Decode.

/** Encode the image data for Intra pictures with adaptive PQ (minmax).
The encoder seeks to find the optimal quant value for each macroblock using a minmax algorithm with
the constraint of a max number of bits specified in the method parameter list by allowedBits.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: 1/0 = do/do not update ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int len = _codec->_mbLength;
	int mb;
	/// Mark the macroblock from where min bit rate macroblocks must be encoded if the slice is to be truncated.
	int minMBIndex = len;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPIntra;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Initialisation step: 
	///		lower(D,R) : QP = H264V2_MAX_QP.
	///		upper(D,R) : QP = 1.
	/// Note that the D values represent the worst (max) distortion of only one macroblock in the entire
	/// frame but the R values represent the accumulated (total) rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int mbDmax = 0;
	int	invalidated = 0;
	int	iterations = 0;
	/*
	  /// --------------------- I-Frame Measurement Collection -----------------------------------------------------
	  /// --------------------------------------------------------------------------------------------------
	*/
	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest (max) distortion of all macroblocks.
		Rl += _codec->ProcessIntraMbImplStd(pMb, 1);
		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the macroblock with the peak distortion.
		}//end if _distortion...

	}//end for mb...

  /// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer and assume half required after exiting.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_intraIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (start - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt else do damage control.
	int bitCost = Rl;
	int oldBitCount = Rl;
	if (Rl <= allowedBits)
	{
		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	/// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int goingDown = 1;
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			int model = 0;
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
			{
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);
				model = 1;
			}//end if linear...

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
			{
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.
				model = 2;
			}//end if bisection...

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;

			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// If the previous neighbourhood has not changed and QP is the same as the last encoding of this blk
				/// then it does not have to be re-encoded assuming distortion < Dmax.
				if ((mb >= firstMbChange) || (_pQ[mb] != pMb->_mbEncQP) || (pMb->_distortion[_pQ[mb]] > Dmax))
				{
					/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					pMb->_mbQP = _pQ[mb];
					if (_pQ[mb] > 24)  ///< Assume that below QP = 24 the prediction mode will be the same.
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 0, Dmax, qEnd);
					else
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 1, Dmax, qEnd);
					_pQ[mb] = pMb->_mbQP;

					if (mb < firstMbChange)
						firstMbChange = mb;
				}//end if mb...
				else
					R += pMb->_rate[_pQ[mb]];

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 
			}//end for mb...

	//			for(mb = 0; mb < len; mb++)
	//			{
	//				MacroBlockH264* pMb = &(_codec->_pMb[mb]);
	//				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, 1);
	//				R += pMb->_rate[_pQ[mb]];
	//      }//end for mb...

				/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		/// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _pQ[mb];
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax path Allowed=%d Cost=%d Invalid=%d", allowedBits, R, invalidated);
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax");
		bitCost = R;

	}//end if Rl...
	else ///< For QP = H264V2_MAX_QP the max allowed bits was exceeded and damage control is required.
	{
		///======================================================================================

		/// Sub-optimal Steepest Ascent Algorithm
		bitCost = DamageControl(allowedBits, bitCost);

		if (bitCost >= allowedBits) ///< All failed.
		{
			minMBIndex = _codec->_lumWidth / 16; ///< Hope for the best.
			invalidated = 1;
			for (int mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _codec->_pMb[mb]._mbEncQP;
		}//end if bitCost...

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "I-frame: Damage control path Allowed=%d Cost=%d Iter=%d ListLen=%d ReorderCnt=%d", allowedBits, bitCost, iterations, listLen, cnt);
		//sprintf(_codec->_errorInfo, "I-frame: Damage control");

	}//end else...

	/// Apply the selected quant with the full feedback loop to all macroblocks.
	if (invalidated)
	{
		//  	int bitCount = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// Encode the macroblocks until min null macroblocks.
			if (mb < minMBIndex)
				_codec->ProcessIntraMbImplStd(pMb, 0);
			//  			bitCount += _codec->ProcessIntraMbImplStd(pMb, 1);
			else
				_codec->ProcessIntraMbImplStdMin(pMb);
			//  			bitCount += _codec->ProcessIntraMbImplStdMin(pMb);

		}//end for mb...

  //    bitCost = bitCount;

	}//end if invalidated...

	*bitsUsed = 0;
	//  *bitsUsed = bitCost;
	return(1);
}//end IntraImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm
At max QP for all Mbs the rate limit is exceeded and an alternative quantisation
approach is taken to use the available bits as best as possible. This implementation
zeros more and more of the DCT coeffs until it fits using a sub-optimal Steepest
Ascent Algorithm.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used up to this point.
@return             : The actual bits consumed.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	int i, mb;
	int bitCost = currBitCost;
	int iterations = 0;
	int cnt;

	/// Initialise the ordered mb list.
	int len = _codec->_mbLength;
	int listLen = len;
	for (mb = 0; mb < len; mb++)
		_pMbList[mb] = mb;

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the mbs in increasing distortion.

			/// Exclude completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (_codec->_pMb[mb]._mbEncQP < H264V2_I_MAX_EXT_QP)
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_I_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_I_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 66; break;
					case 66: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 77; break;
					case 77: pMb->_mbQP = 81; break;
					case 81: pMb->_mbQP = 84; break;
					case 84: pMb->_mbQP = 85; break;
					case 85: pMb->_mbQP = 86; break;
					default: pMb->_mbQP = 86; break;
					}///end switch _mbEncQP...

					_codec->ProcessIntraMbImplStd(pMb, 2, 1); ///< Distortion only and without pred mode selection.

				}//end while _distortion[]...

				/// Add back new bits.
				pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
				predR += pMb->_rate[pMb->_mbEncQP];

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessIntraMbImplStd(pMb, 1, 1);
		}//end for mb...

		iterations++;
	}//end while bitCost...

	return(bitCost);
}//end IntraImgPlaneEncoderImplMinMax::DamageControl.

/** Encode the image data for Intra IDR pictures with a mb Dmax limit.
Process all slices and their macroblocks in order. The QP value is decremented
until the mb Dmax is less than the codec _dMax parameter. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the Dxax search is limited to.
	int qEnd = _codec->_minQPIntra;
	int coeffBits = 0;

	if (_codec->_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)
		if ((_codec->_iPictureDMaxMultiplier != 0) || (_codec->_iPictureDMaxMultiplier != 0))
			/// Modify the Dmax value by the I-Picture multiplier and fraction.
			dmax = (dmax * _codec->_iPictureDMaxMultiplier) + ((dmax * _codec->_iPictureDMaxFraction) / 10);

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		/// Descend the QP value until the mb distortion is less than dmax.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessIntraMbImplStd(pMb, 1, 0, dmax, qEnd);
		else
			_codec->ProcessIntraMbImplStd(pMb, 2, 0, dmax, qEnd);
	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplDMax::Encode.

/** Get distortion from an r vs d power model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistPowerModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if ((dl != du) && (rl != ru))
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a power function.
		double beta = -(log((double)rl / (double)ru)) / (log((double)dl / (double)du));
		double alpha = (double)rl / (pow((double)dl, -beta));
		/// Use the power function to predict where r will be. r = alpha.d^(-beta)
		d = (int)exp(-log((double)r / alpha) / beta);
	}//end if dl...

	return(d);
}//end FitDistPowerModel.

/** Get distortion from an r vs d linear model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistLinearModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if (rl != ru)
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a linear function.
		d = (int)((double)((r - rl)*(dl - du)) / (double)(rl - ru)) + dl;
	}//end if dl...

	return(d);
}//end FitDistLinearModel.

/** Get the next quant QP value that has a distortion less than Dmax.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra)
{
	/// 1st iteration required to ensure sync with macroblock dependencies if
	/// it was invalidated or changed since last encoding.
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);

		di = mb._distortion[i];
	}//end if mbIndex...

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if (i < H264V2_MAX_QP)
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
//			int previ = i;
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				//				previ = i;
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmax.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// The delta QP for a mb is constrained to {-26...25}. Therefore if
	/// the current QP value results in a dQP > 25 or < -26 then it must 
	/// be reprocessed before continuing regardless of the Dmax value. The
	/// i not equal to atQ signals that delta QP was out of range.
	int prevQP = GetPrevMbQP(&mb);
	int minQP = prevQP - 26;
	if (minQP < lowestQ) minQP = lowestQ;
	int maxQP = prevQP + 25;
	if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
	if (i < minQP) i = minQP;
	else if (i > maxQP) i = maxQP;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb or delta QP was out of range then
  /// its dependencies have been altered and it must be re-encoded.
	if ((mbIndex >= lclChangeMb) || (i != atQ))
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
			else
				ProcessInterMbImplStd(&mb, 0, 2);         ///< Distortion only.
		}//end if !intra...
		else
			ProcessIntraMbImplStd(&mb, 2, 0); ///< Distortion only.

		di = mb._distortion[i];
	}//end if mbIndex...

	/// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 2);
			else
				ProcessIntraMbImplStd(&mb, 2, 1); ///< Distortion only without pred mode selection.

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

  /// Set the new mb rate at this QP value.
	if (!intra)
	{
		int rate = 0;
		if (!mb._skip)
			rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
		mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.
	}//end if !intra...
	else
		mb._rate[mb._mbEncQP] = MacroBlockLayerBitCounter(&mb);

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer2.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
This method includes extended QP values = {52..71}.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
			{
				if (mb._mbQP > H264V2_MAX_QP)              ///< For extended QP range, temporarily reset for processes below.
					mb._mbQP = H264V2_MAX_QP;

				int rate = 0;
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
				if (!mb._skip)
					rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
				mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.

				mb._mbQP = i;                             ///< Put it back.
			}//end if _mbEncQP...
			else
			{
				ProcessInterMbImplStd(&mb, 0, 1);
			}//end else...

		}//end if !intra...
		else
		{
			ProcessIntraMbImplStd(&mb, 1);
		}//end else...

		di = mb._distortion[i];
	}//end if mbIndex...

  /// The delta QP for a mb is constrained to {-26...25}. Therefore if
  /// the current QP value results in a dQP > 25 or < -26 then it must 
  /// be reprocessed before continuing regardless of the Dmax value.
	int minQP = lowestQ;
	if (i <= H264V2_MAX_QP) ///< Only for the non-extended QP range.
	{
		int prevQP = GetPrevMbQP(&mb);
		minQP = prevQP - 26;
		if (minQP < lowestQ) minQP = lowestQ;
		int maxQP = prevQP + 25;
		if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
		if ((i < minQP) || (i > maxQP))
		{
			if (i < minQP) i = minQP;
			else i = maxQP;
			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];
		}//end if i...
	}//end if i...

	  /// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer3.

/** Get the next quant QP value that has a distortion less than Dmax with approximations.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param epsilon			: The Dmax approximation only has to be within epsilon of Dmax.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra)
{
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded. However, as it will be changed anyway, either up
	/// or down, a short cut approximation is to assume that the previous encoding at the
	/// current QP is approximately correct and the descent/ascent proceeds with these values.
	/// But the mb must be processed at least once before exiting to be valid.
	int atLeastOnce = 0;

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i < H264V2_MAX_QP) && ((Dmax - di) > epsilon))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Re-sync the mb if it was not already processed.
	if ((mbIndex >= lclChangeMb) && (!atLeastOnce))
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);
	}//end if mbIndex...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmaxApprox.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		: Macroblock to operate on.
@param withDR	: With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@return				: Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode and get the prediction. Pred stored in _16x16.
	pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
	if (withDR)
		pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop. The distortion returned includes ROI modification.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...

      /// Region of interest modification.
      mbDistortion = ROIDistortion(pMb->_mbIndex, mbDistortion);
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
  if (withDR)
    pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock with a max distortion criterion.
Code factoring usage. Includes reading the input image, IT, quantisation, vlc encoding and
determining coding patterns, type, etc. _mbQP is decremented until the lum distortion is
below Dmax. If distortion for the given _mbQP is below Dmax then the mb is processed only
once, there is no ascent search. _mbQP must be less than or equal to H264V2_MAX_QP, coeff
zeroing is not implemented in this overload. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined as the starting QP value before this method is called.

  /// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.

  /// Frame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _Lum->Read(c, r);
					if (c)
						prev = _Lum->Read(c - 1, r); ///< Left.
					else
						prev = _Lum->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation --------------------------------------------
	/// Implement the forward and feedback loop into the temp blks. The block coeffs are still 
  /// required for the context-aware vlc coding and therefore the temporary working blocks are
  /// used in the feedback loop. The mb QP will change during the TransAndQuantIntra16x16MBlk() 
  /// method call.
	if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantIntra16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Feedback loop -------------------------------------------------------

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// Distortion with Lum input was calculated in the TransAndQuantIntra16x16MBlk() method. 

	  /// ------------------ Set patterns and type -----------------------------------------------
	  /// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	  /// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
	{
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE) ///< Requires coeff bits without the mb header bits.
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerCoeffBitCounter(pMb);
		else
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);
	}//end if withDR...

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
and ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisation(MacroBlockH264* pMb)
{
	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs of lum and chr are zeroed. {67..69} The AC coeffs of the Chr DC 
	/// 2x2 coeffs additionally zeroed. {70..84} AC coeffs of the Lum DC coeffs additionally 
	/// zeroed. {85} DC coeff of the Chr DC 2x2 coeffs zeroed. {86} DC coeff of the Lum DC 
	/// coeffs zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	int lumDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 69)  ///< Include AC coeff of Chr DC for QP = {67..69}.
	{
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 84)  ///< Include AC coeffs of Lum DC and all AC coeffs of Chr DC for QP = {70..84}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 3; ///< Not the Chr DC term.
		lumDcCoeffZeroed = pMb->_mbEncQP - 69;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 85)  ///< Include all Chr DC coeffs but only AC coeffs of Lum DC for QP = {85}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4; ///< ...and Chr DC term.
		lumDcCoeffZeroed = 15;
	}//end else if _mbEncQP...
	else  ///< All zeroed for QP = {86} and above.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
		lumDcCoeffZeroed = 16;
	}//end else...

	int startPos4x4 = 16 - acCoeffZeroed;
	int startChrDcPos2x2 = 4 - chrDcCoeffZeroed;
	int startLumDcPos4x4 = 16 - lumDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_DC; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_LUM_DC) && (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else if ((blk == MBH264_CB_DC) || (blk == MBH264_CR_DC)) ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startChrDcPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else if blk...
		else ///< if(blk == MBH264_LUM_DC) Lum DC AND zero'ing required.
		{
			if (lumDcCoeffZeroed)
			{
				for (i = startLumDcPos4x4; i < 16; i++)
				{
					if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ4x4[i]] = 0;
				}//end for i...
			}//end if lumDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisation.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
an ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring. Ver 2 optimises the process used
in the original version.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisationVer2(MacroBlockH264* pMb)
{
	//////////////////////////////////////////////////////////////////////////
	  // if(pMb->_mbEncQP <= H264V2_MAX_QP + 15) return; ///< Why are we here?
	//////////////////////////////////////////////////////////////////////////

	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71} 
	/// Lum DC coeffs additionally zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 70)  ///< Include Chr DC coeffs for QP = {67..70}.
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
	}//end else...
	int startPos4x4 = 16 - acCoeffZeroed;
	int startPos2x2 = 4 - chrDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude Chr DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else  ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisationVer2.

/** The absolute min bit encoding of a Std Intra macroblock.
Set and measure the encoding for a min bit implementation of the std Intra
macroblock. This only includes DC prediction and all residual DC and AC
coeffs are zero'ed. QP is set to max. Return the bit cost.
@param pMb	: Macroblock to operate on.
@return		  : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStdMin(MacroBlockH264* pMb)
{
	int rate = 0;
	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_mbQP = H264V2_MAX_QP;
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	/// Force the selection to DC Lum prediction for all macroblocks.
	pMb->_intra16x16PredMode = MacroBlockH264::Intra_16x16_DC;
	GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);

	_RefLum->Write16x16(*(_16x16)); ///< Write the prediction into the ref.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);

	pMb->_intraChrPredMode = MacroBlockH264::Intra_Chr_DC;
	GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
	GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);

	_RefCb->Write8x8(*(_8x8_0));
	_RefCr->Write8x8(*(_8x8_1));

	/// Clear all mb coeffs for encoding. Implies all difference DC and AC coeffs are zero.
	for (int blk = 0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		(pBlk->GetBlkOverlay())->Clear();
		pBlk->SetNumCoeffs(0);
	}//end for blk...

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. For Intra slices
	/// no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;
	if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	///< Previous macroblock within same slice.
			pMb->_mb_qp_delta = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate --------------------------------------------------------
	rate = MacroBlockLayerBitCounter(pMb);

	return(rate);
}//end ProcessIntraMbImplStdMin.

/** Encode the image data for Inter pictures.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Create an img to capture the difference between the input img 
  /// and the motion comp pred img. The collection is done per mb and dumped to file after.
  //int selectedFrameNum = 0;
  ////int selectedFrameList[15] = {19, 78, 93, 148, 152, 154, 156, 173, 182, 194, 204, 207, 213, 216, 221}; ///< Foreman
  ////int selectedFrameList[7] = {24, 62, 126, 184, 210, 258, 278}; ///< Mobile
  //int selectedFrameList[9] = {15, 24, 52, 114, 124, 152, 226, 256, 288}; ///< Soccer
  //for(int i = 0; i < 9; i++)
  //{
  //  if(_codec->_frameNum == selectedFrameList[i])
  //    selectedFrameNum = _codec->_frameNum;
  //}//end for i...

  //short* pDiffLum = NULL;
  //short* pDiffCb  = NULL;
  //short* pDiffCr  = NULL;
  //OverlayMem2Dv2* diffLum	= NULL;
  //OverlayMem2Dv2* diffCb	= NULL;
  //OverlayMem2Dv2* diffCr	= NULL;

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  pDiffLum = new short[(_codec->_lumWidth * _codec->_lumHeight) + 2*(_codec->_chrWidth * _codec->_chrHeight)];
  //  pDiffCb = &(pDiffLum[_codec->_lumWidth * _codec->_lumHeight]);
  //  pDiffCr = &(pDiffLum[(_codec->_lumWidth * _codec->_lumHeight) + (_codec->_chrWidth * _codec->_chrHeight)]);

	 // diffLum	= new OverlayMem2Dv2(pDiffLum, _codec->_lumWidth, _codec->_lumHeight, _codec->_lumWidth, _codec->_lumHeight);
	 // diffCb	= new OverlayMem2Dv2(pDiffCb, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);
	 // diffCr	= new OverlayMem2Dv2(pDiffCr, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);

  //  /// Copy the input img into the diff img from where the comp pred img will be subtracted.
  //  _codec->_Lum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  _codec->_Cb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Cr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Lum->SetOrigin(0, 0);
  //  _codec->_Cb->SetOrigin(0, 0);
  //  _codec->_Cr->SetOrigin(0, 0);

  //  diffLum->Write(*_codec->_Lum);
  //  diffCb->Write(*_codec->_Cb);
  //  diffCr->Write(*_codec->_Cr);

  //  /// Restore blk dimensions.
  //  diffLum->SetOverlayDim(16, 16);
  //  diffCb->SetOverlayDim(8, 8);
  //  diffCr->SetOverlayDim(8, 8);
  //  _codec->_Lum->SetOverlayDim(4, 4);
  //  _codec->_Cb->SetOverlayDim(4, 4);
  //  _codec->_Cr->SetOverlayDim(4, 4);
  //}//end if _frameNum...
  /////////////////////////////////////////////////////////////////////////////////////////////

	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		/////////////////////////////////////////////////////////////////////////////////////////////
		/// Research Data Collection: Mb data capture.
		//if(_codec->_frameNum == selectedFrameNum)
		//{
		   // diffLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // diffCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // diffCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  _codec->_RefLum->SetOverlayDim(16, 16);
		//  _codec->_RefCb->SetOverlayDim(8, 8);
		//  _codec->_RefCr->SetOverlayDim(8, 8);
		   // _codec->_RefLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // _codec->_RefCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // _codec->_RefCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  diffLum->Sub(*_codec->_RefLum);
		//  diffCb->Sub(*_codec->_RefCb);
		//  diffCr->Sub(*_codec->_RefCr);

		//  _codec->_RefLum->SetOverlayDim(4, 4);
		//  _codec->_RefCb->SetOverlayDim(4, 4);
		//  _codec->_RefCr->SetOverlayDim(4, 4);
		//}//end if _frameNum...
		/////////////////////////////////////////////////////////////////////////////////////////////

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this macroblock as the median of the neighbourhood 
		/// vectors and subtract it from the macroblock vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
		pMb->_mbQP = _codec->_slice._qp;
		_codec->ProcessInterMbImplStd(pMb, addRef, 0);

	}//end for mb...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Dump to file and clean up in reverse order.

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  char* filenameBase = "c:/keithf/Videos/StdTestVideos/Soccer352x288_30fps";
  //  char  sQP[8];
  //  char  sFrmNum[16];
  //  char sFilename[512];
  //  char sFilenameFinal[512];

  //  strcpy(sFilename, (const char*)filenameBase);
  //  strcat(sFilename, (const char*)"_qp");
  //  strcat(sFilename, (const char*)(_itoa(_codec->_slice._qp, sQP, 10)));
  //  strcat(sFilename, (const char*)"_frm");
  //  strcat(sFilename, (const char*)(_itoa(selectedFrameNum, sFrmNum, 10)));

  //  diffLum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  diffLum->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_lum.csv");
  //  diffLum->Dump(diffLum, sFilenameFinal, "");

  //  diffCb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCb->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cb.csv");
  //  diffLum->Dump(diffCb, sFilenameFinal, "");

  //  diffCr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCr->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cr.csv");
  //  diffLum->Dump(diffCr, sFilenameFinal, "");
  //}//end if _frameNum...

  //if(diffCr != NULL)
  //  delete diffCr;
  //if(diffCb != NULL)
  //  delete diffCb;
  //if(diffLum != NULL)
  //  delete diffLum;

  //if(pDiffLum != NULL)
  //  delete[] pDiffLum;
  /////////////////////////////////////////////////////////////////////////////////////////////

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplStdVer1::Encode.

/** The forward and inverse loop of a Std Inter macroblock.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

	/// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------------
	if (pMb->_mbEncQP > H264V2_MAX_QP)
		CoeffZeroingQuantisationVer2(pMb);
	/*
	  {
		int blk, i;
		const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
		const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

		/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
		/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that
		/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71}
		/// Lum DC coeffs additionally zeroed.
		int acCoeffZeroed     = 15; ///< By default.
		int chrDcCoeffZeroed  = 0;
		if( pMb->_mbEncQP <= (H264V2_MAX_QP + 15) )
		  acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
		else if( pMb->_mbEncQP <= 70 )  ///< Include Chr DC coeffs for QP = {67..70}.
		{
		  chrDcCoeffZeroed = pMb->_mbEncQP - 66;
		}//end else if _mbEncQP...
		else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
		{
		  acCoeffZeroed     = 16;
		  chrDcCoeffZeroed  = 4;
		}//end else...
		int startPos4x4 = 16 - acCoeffZeroed;
		int startPos2x2 = 4 - chrDcCoeffZeroed;

		/// Zero coeff in the mb according to the QP rules above.
		  for(blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
		  {
			  BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		  short* pB = pBlk->GetBlk();

		  if( (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC) )  ///< Exclude Chr DC blks.
		  {
			for(i = startPos4x4; i < 16; i++)
			{
			  if( pB[pZZ4x4[i]] )  ///< Only need to change coeffs that are not already zero.
				pB[pZZ4x4[i]] = 0;
			}//end for i...
		  }//end if blk...
		  else  ///< Chr DC blks AND zero'ing required.
		  {
			if(chrDcCoeffZeroed)
			{
			  for(i = startPos2x2; i < 4; i++)
			  {
				if( pB[pZZ2x2[i]] )  ///< Only need to change coeffs that are not already zero.
				  pB[pZZ2x2[i]] = 0;
			  }//end for i...
			}//end if chrDcCoeffZeroed...
		  }//end else...

		  }//end for blk...

	  }//end if _mbEncQP...
	*/
	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			InverseTransAndQuantInter16x16MBlk(pMb, 1);

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));            ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the Distortion & Rate and store results ----------------------------------
	/// Store distortion for this quant value.
	if (withDR)
	{
		/// Calc distortion with Input. If there was a coded blk pattern then compare with temp img else
	  /// with the unaltered ref img.
		OverlayMem2Dv2* pLI = _RefLum;
		OverlayMem2Dv2* pCbI = _RefCb;
		OverlayMem2Dv2* pCrI = _RefCr;
		if (pMb->_coded_blk_pattern)
		{
			pLI = _16x16;
			pCbI = _8x8_0;
			pCrI = _8x8_1;
		}//end else if _coded_blk_pattern...

#ifdef USE_ABSOLUTE_DIFFERENCE
		distortion += pLI->Tad16x16(*_Lum);	///< Total abs distortion between Ref and input Lum.
		distortion += pCbI->Tad8x8(*_Cb);
		distortion += pCrI->Tad8x8(*_Cr);
#else
		distortion += pLI->Tsd16x16(*_Lum);	///< Total square distortion between Ref and input Lum.
		distortion += pCbI->Tsd8x8(*_Cb);
		distortion += pCrI->Tsd8x8(*_Cr);
#endif
    /// Modify the distortion with the region of interest map.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);
		pMb->_distortion[pMb->_mbEncQP] = distortion;

		//    if(!pMb->_skip)
		//		  rate = MacroBlockLayerBitCounter(pMb);
		//    else
		if (pMb->_skip)
		{
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (int i = 1; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _skip...

	//    pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	/// Store rate for this quant value if required.
	if ((withDR == 1) && (!pMb->_skip)) ///< For withDR = 2, no rate calculation is done.
	{
		rate = MacroBlockLayerBitCounter(pMb);
		pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	return(rate);
}//end ProcessInterMbImplStd.

/** The forward and inverse loop of a Std Inter macroblock with a Dmax criterion.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Includes accumulation of the frame MAD measure.
Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	/// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

  /// Fame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _16x16->Read(c, r);
					if (c)
						prev = _16x16->Read(c - 1, r); ///< Left.
					else
						prev = _16x16->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
  /// Includes the distortion calc and the inverse quant and transform to the temp blks. For 
  /// extended range QP > H264V2_MAX_QP the appropriate coeffs are zeroed. 
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantInter16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
	/// The inverse to the temp blks was included in the TransAndQuantInter16x16MBlk() method above.

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));  ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the rate and store results ----------------------------------
	if (withDR && pMb->_skip)
	{
		/// Ensure coeffs settings are synchronised for future use by mb neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end if withDR...

	/// Store rate for this quant value if required.
	if (!pMb->_skip)
	{
		if ((withDR == 1) || (withDR == 3)) ///< For withDR = 2, no rate calculation is done.
		{
			rate = MacroBlockLayerCoeffBitCounter(pMb);
			pMb->_rate[pMb->_mbEncQP] = rate;
		}//end if withDR...
	}//end if !skip...

	return(rate);
}//end ProcessInterMbImplStd.

/// Does NOT include motion prediction and compensation. Assumes these mb members are already set before called.
int H264v2Codec::ProcessInterMbImplStdMin(MacroBlockH264* pMb)
{
	/// Set the difference to the compensated reference to zero and therefore no operation needs to be
	/// performed on the ref. Zero and clear all blocks.

	  /// NB: _mbQP must be correctly defined before this method is called.
	int rate = 0;

	/// Base settings for all inter macroblocks.
	pMb->_intraFlag = 0;
	pMb->_skip = 0;

	/// Clear the delta quantisation parameter and set the _mbQP to the same as the previous non-skipped mb. The
  /// _mbQP does not have any impact because all coeffs are set to zero.
	pMb->_mb_qp_delta = 0;
	/// Find the previous non-skipped macroblock.
	int prevMbIdx = pMb->_mbIndex - 1;
	/// Re-align the quantisation param for future delta qp calculations.
	if (prevMbIdx >= 0)
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
			pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mbQP = _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mbQP = _slice._qp;

	/// Force all values to zero before encoding.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);
	_16x16->Clear();
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_0->Clear();
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);
	_8x8_1->Clear();

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode. If motion is zero then mb is skipped.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	if (!pMb->_skip)
		rate = MacroBlockLayerBitCounter(pMb);
	else
	{
		/// Ensure coeffs settings are synchronised for future use by neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end else...

	pMb->_rate[0] = rate;

	return(rate);
}//end ProcessInterMbImplStdMin.

/** Calc delta QP based on macroblock QP.
The coded block pattern, _intraFlag and _mbQP values must be correctly set before calling this
method. The _skip mode for P mbs alters the _mbQP value.
@param pMb    : Macroblock to operate on.
@return       : Delta QP for these mb parameters.
*/
int H264v2Codec::GetDeltaQP(MacroBlockH264* pMb)
{
	int deltaQP = 0;

	/// Find the previous non-skipped macroblock. For Intra slices no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;

	if (pMb->_coded_blk_pattern || pMb->_intraFlag)
	{
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				deltaQP = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
			else
				deltaQP = pMb->_mbQP - _slice._qp;
		}//end if prevMbIdx...
		else
			deltaQP = pMb->_mbQP - _slice._qp;
	}//end if _coded_blk_pattern...
	else
	{
		/// Re-align the quantisation param for future delta qp calculations.
		if (prevMbIdx >= 0)
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
			else
				pMb->_mbQP = _slice._qp;
		}//end if prevMbIdx...
		else
			pMb->_mbQP = _slice._qp;
	}//end else...

	return(deltaQP);
}//end GetDeltaQP.

/** Get the previous macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Previous Mb QP.
*/
int H264v2Codec::GetPrevMbQP(MacroBlockH264* pMb)
{
	int prevMbIdx = pMb->_mbIndex - 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((prevMbIdx >= 0) && (pMb->_slice == _pMb[prevMbIdx]._slice))
		return(_pMb[prevMbIdx]._mbQP);
	else
		return(_slice._qp);
}//end GetPrevMbQP.


/** Get the next macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Next Mb QP.
*/
int H264v2Codec::GetNextMbQP(MacroBlockH264* pMb)
{
	int nextMbIdx = pMb->_mbIndex + 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((nextMbIdx < _mbLength) && (pMb->_slice == _pMb[nextMbIdx]._slice))
		return(_pMb[nextMbIdx]._mbQP);
	else
		return(pMb->_mbIndex);
}//end GetPrevMbQP.

/** Encode the image data for Inter pictures with QP adaptation at macroblock level.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 + X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
The macroblock wide _mbPQ is adapted to ensure that the resulting stream will use
no more than allowedBits. This algorithm uses a bisection technique to minimise the
max distortion by adapting the macroblock quant value until the nearest rate to the
total allowable bits is achieved.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb, bitCount;
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int minMBIndex = len; ///< Mark the macroblock from where min units must be encoded.

	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

  /// Mark this time point for later use.
	int preMotionTime = 0;
	if (_codec->_timeLimitMs)
		preMotionTime = (int)_codec->GetCounter();

	///	---------------------- Motion Vector encoding ---------------------------------------

	/// In this implementation QP adaptation is performed after full motion compensation.
	/// Get the motion vector list to work with. Assume SIMPLE2D type list.
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

	/// Prepare the compensation on a per macroblock basis.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Count the bits used for the motion vectors by iterating through the
	/// macroblocks and encoding the differential motion vector diff (_mvdX,_mvdY). 
  /// Check that there are sufficient bits available for each vector. If not then 
  /// truncate the estimation result and mark all remaining macroblocks as skipped. 
  /// Store the bit cost of the mb with only motion vectors coded in _rate[0].
	int bitCost = 0;
	int mbSkipRun = 0;
	/// Start with all mbs skipped to the end by counting bits for mbSkipRun = len;
	int minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(len);
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Set the mb with the the motion vector, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors and subtract from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		/// Motion compensate the macroblock.
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		int lclAllowedBits = (allowedBits - bitCost) - minPictureBitsToEnd;	///< So far before encoding this MVD pair.

	  /// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);

		/// For skipped mbs, the previous skipped bit count must be included in the minPictureBitsToEnd.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			lclBitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Are there enough bits left to encode this run + MVD pair?
			if (lclBitCost < lclAllowedBits)
				bitCost += lclBitCost;  ///< Update the accumulator.
			else	///< Truncation condition.
			{
				/// Clean up all remaining macroblocks as skipped and exit. In this implementation
				/// when there are not enough bits to encode all the motion vectors the estimated list
				/// is truncated with [0,0] difference vectors or [0,0] motion with special conditions 
			  /// and re-compensated.
				return(DamageControlMvOnly(allowedBits, bitsUsed));
			}//end else...

			mbSkipRun = 0; ///< Reset.

		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;

		/// Update remaining bits for next mb where all remaining mbs are skipped.
		int mbSkippedToEnd = mbSkipRun + ((len - 1) - mb);
		if (mbSkippedToEnd)
			minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkippedToEnd);
		else
			minPictureBitsToEnd = 0;
	}//end for mb...
  /// Include the last run to the end.
	bitCost += minPictureBitsToEnd;
	if (bitCost >= allowedBits)  ///< ...and check.
		return(DamageControlMvOnly(allowedBits, bitsUsed));
	int minMvBitsToEnd = bitCost;	///< Hold the total motion vector with zero residual bit cost.

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock Q search.
	-------------------------------------------------------------------------------------------
	*/
	/// Initialisation step: 
	  ///		lower(D,R) : QP = H264V2_MAX_QP.
	  /// Note that the D values represent the worst distortion of only one macroblock in the entire
	  /// frame but the R values represent the accumulated rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int iterations = 0;
	int	invalidated = 0;
	int mbDmax = 0;

	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
	  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
		Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		if (!pMb->_skip)
		{
			/// Sum of skip run and coded mb bits accumulated.
			Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the mb index with the peak distortion.
		}//end if _distortion...

		/// No early exit because damage control uses this result = Rl.

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer but exclude the motion estimation time
  /// as an offset.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_interIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (preMotionTime - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt from quant param = H264V2_MAX_QP, else do damage control.
	if (Rl <= allowedBits)
	{

		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	  /// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;
			mbSkipRun = 0;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, false);
				R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
				if (!pMb->_skip)
				{
					/// Sum of skip run and coded mb bits accumulated.
					R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
					mbSkipRun = 0;
				}//end if !_skip...
				else
					mbSkipRun++;

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 

			}//end for mb...
	    /// Add last skip run.
			if (mbSkipRun)
				R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		    /// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
			{
				_codec->_pMb[mb]._mbQP = _pQ[mb];
				_codec->_pMb[mb]._mbEncQP = _pQ[mb];
			}//end for mb...
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "P-frame: all good Allowed=%d Cost=%d", allowedBits, R);

	}//end if Rl...
	else	///< Damage control.
	{
		bitCost = DamageControl(allowedBits, Rl);

		if (bitCost >= allowedBits) ///< All failed.
			minMBIndex = 0;

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "P-frame: damage control Allowed=%d Cost=%d", allowedBits, bitCost);

	}//end else Damage control...

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock final encoding.
	-------------------------------------------------------------------------------------------
	*/
	/// Rip through each macroblock as a linear array and process each block within the macroblock.
	/// The _mbEncPQ values have been set in the above encoding.
	mbSkipRun = 0;
	bitCount = 0;
	for (int mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// Encode the mbs and add to Ref img until min null mb position.
		if (mb < minMBIndex)
		{
			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
	  //      bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 0);
			bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 1);
		}//end if mb...
		else
			bitCount += _codec->ProcessInterMbImplStdMin(pMb);
		if (!pMb->_skip)
		{
			bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	*bitsUsed = 0;
	int ret = 1;
	if (bitCount > allowedBits)  ///< Failed to meet bit target.
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bit target unattainable";
		ret = 0;
	}//end if bitCount...

	return(ret);
}//end InterImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm for motion vectors only condition.
Clean up all remaining macroblocks as skipped and exit. In this implementation
when there are not enough bits to encode all the motion vectors the estimated list
is truncated with [0,0] difference vectors or [0,0] motion with special conditions
and re-compensated.
@param allowedBits  : Bits to use.
@param bitsUsed     : Bits consumed on the stream.
@return             : 1 = success, 0 = failed.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControlMvOnly(int allowedBits, int* bitsUsed)
{
	int mb;
	/// Stage 1: Start by taking a snapshot of improvement (mostly negative) in distortion between
	/// the current estimated mv and the predicted mv per mb. Count the total bit rate to determine
	/// how far off from the allwedBits these mvs are.
	int len = _codec->_mbLength;
	int bitCost = 0;
	int mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
		pMb->_include = 1;  ///< Default.

		/// Set the mb with the the mv, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		int topLeftX = pMb->_offLumX;
		int topLeftY = pMb->_offLumY;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

		/// Compensate with the pred mv and measure the mb distortion.
		_codec->_pMotionCompensator->Invalidate();
		_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, predX, predY);
		int distortion = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);

		if ((mvx != predX) || (mvy != predY))  ///< Only if the estimated mv and the pred mv are not already equal.
		{
			_codec->_pMotionCompensator->Invalidate();
			_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, mvx, mvy);
			pMb->_distortion[0] = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);
		}//end if mvx...
		else
		{
			/// Estimated mv is equal to pred mv.
			pMb->_distortion[0] = distortion;
			pMb->_include = 0;
		}//end else...

		/// Expected increase in distortion by choosing the pred mv.
		_pDistortionDiff[mb] = distortion - pMb->_distortion[0];

		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Set the mv difference before processing the mb.
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
		/// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);
		/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			bitCost += (lclBitCost + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
			mbSkipRun = 0; ///< Reset.
		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;
	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Stage 2: Sub optimal solution proceeds by scanning the next mb with the initial least distortion 
	/// impact after replacing the estimated mv with the pred mv. Continue to replace the mv with the 
	/// pred mv until the accumulated bits are approximately below the allowed bits ignoring the skip run
	/// bit run contribution. Rely on the initial _rate[0] calculation above to guess the rate savings. 
	/// Then re-calculate actual bits at the end to determine whether or not the loop must continue.
	int forceStop = 0;
	while ((bitCost > allowedBits) && !forceStop)
	{
		///--------------------------------------------------------------------------------------
		int bitSavingRequired = bitCost - allowedBits;
		int savedBits = 0;
		while ((savedBits < bitSavingRequired) && !forceStop)
		{
			int currentLowestDistDiff = 0x7FFFFFFF; ///< Very large starting point.
			/// Find the next lowest distortion difference.
			int nextMb = -1;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
				if (pMb->_include && (_pDistortionDiff[mb] < currentLowestDistDiff))
				{
					currentLowestDistDiff = _pDistortionDiff[mb];
					nextMb = mb;
				}//end if _include...
			}//end for mb...

			if (nextMb >= 0) ///< A candidate mb was found.
			{
				/// Approximate the saving by the existing rate[0] value by assuming that
				/// this mb will be skipped. Ignore the savings on the improved skip run.
				savedBits += _codec->_pMb[nextMb]._rate[0];
				/// Exclude from further checks.
				_codec->_pMb[nextMb]._include = 0;
			}//end if nextMb...
			else
				forceStop = 1;

		}//end while savedBits...

		///--------------------------------------------------------------------------------------
		/// Re-process each mb and accumulate the bit cost. All mbs that are not included must
		/// be set to the pred mv. Only those mbs where the mv has changed are re-compensated.
		bitCost = 0;
		mbSkipRun = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// The pred mv may now be different.
			int predX, predY;
			MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

			if (!pMb->_include)  ///< Marked as a previously predicted mv and mv was set to pred mv.
			{
				/// Set the result mv list to the pred mv.
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 0, predX);
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 1, predY);

				/// Check that this mv is the pred mv.
				if ((pMb->_mvX[MacroBlockH264::_16x16] != predX) || (pMb->_mvY[MacroBlockH264::_16x16] != predY))
				{
					/// Re-compensate if it has changed.
					_codec->_pMotionCompensator->Invalidate();
					_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, predX, predY);
				}//end if _mvX...

			}//end if !include...

			/// Store the motion vector and pred mv in the mb.
			int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
			int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
			pMb->_mvX[MacroBlockH264::_16x16] = mvx;
			pMb->_mvY[MacroBlockH264::_16x16] = mvy;
			pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
			pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
			int r = _codec->ProcessInterMbImplStdMin(pMb);
			/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
			if (!pMb->_skip)
			{
				/// Sum the run and coding bit contributions.
				bitCost += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
				mbSkipRun = 0; ///< Restart
			}//end if !_skip...
			else  ///< Skipped.
				mbSkipRun++;

		}//end for mb...

		/// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	}//end while bitCost...

	/// Check that a solution is possible.
	if (forceStop)
	{
		*bitsUsed = 0;
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Forced stop - no solution possible";
		return(0); ///< Failed.
	}//end if allowedBits...

	  /// ...and then exit.
	int ret = 1;
	if (bitCost > allowedBits)
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bits exceeded in trucation";
		ret = 0;
	}//end if bitCost...

	*bitsUsed = 0;
	return(ret); ///< Something is coded so it is considered successful.
}//end InterImgPlaneEncoderImplMinMax::DamageControlMvOnly.

/** Damage control algorithm
Their are insufficient bits at the max QP and alternative quantisation approaches are required.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used so far for the last encoding of mv and max QP
@return             : Bit cost of this implementation.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	///======================================================================================

	/// Sub-optimal Steepest Ascent Algorithm

	int i, mb;
	int len = _codec->_mbLength;
	int bitCost = currBitCost;
	int iterations = 0;

	/// Initialise the ordered mb list where skipped mbs will never become unskipped and can therefore be excluded.
	int listLen = 0;
	for (mb = 0; mb < len; mb++)
	{
		if (!_codec->_pMb[mb]._skip)
			_pMbList[listLen++] = mb;
	}//end for mb...

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the non-skipped mbs in increasing distortion.

			/// Only included newly skipped and completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (!_codec->_pMb[mb]._skip && (_codec->_pMb[mb]._mbEncQP < H264V2_MAX_EXT_QP))
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			int cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 55; break;
					case 55: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 70; break;
					case 70: pMb->_mbQP = 71; break;
					default: pMb->_mbQP = 71; break;
					}///end switch _mbEncQP...

					_codec->ProcessInterMbImplStd(pMb, 0, 2);

				}//end while _distortion[]...

				/// Add back new bits.
				if (!pMb->_skip)
				{
					pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
					predR += pMb->_rate[pMb->_mbEncQP];
				}//end if !_skip ...

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		int mbSkipRun = 0;
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
			if (!pMb->_skip)
			{
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				mbSkipRun = 0;
			}//end if !_skip...
			else
				mbSkipRun++;

		}//end for mb...
	  /// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		iterations++;
	}//end while bitCost...

	return(bitCost);

	//    if(bitCost >= allowedBits) ///< All failed.
	//		  minMBIndex = 0;

		///======================================================================================
		/*
		/// Sub-optimal Steepest Descent Algorithm

		/// QP = H264V2_MAX_QP for all mbs still uses too many bits so the extended range of QP = {51..71} is
		/// used here to find a near optimal solution.
		int i;
		bitCost = 0;

		/// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		/// Initialise the ordered mb list.
		int listLen = 0;
		mbSkipRun = 0;
		  for(mb = 0; mb < len; mb++)
		  {
		  MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		  _pMbList[listLen++] = mb; ///< Arbitrary order for the mb list.

		  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			  pMb->_mbQP = H264V2_MAX_EXT_QP;

			  /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			  bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		  if(!pMb->_skip)
		  {
			/// Sum of skip run and coded mb bits accumulated.
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		  }//end if !_skip...
		  else
			mbSkipRun++;

			  /// Early exit if this min point is still not possible.
			  if(bitCost >= allowedBits)
				  break;

		  }//end for mb...
		/// Add last skip run.
		if(mbSkipRun)
		  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		R = 0;
		iterations  = 0;

			/// Only proceed if there is hope.
			if(bitCost < allowedBits)
		{
		  /// Starting from highest distortion and lowest rate, slowly decrease the distortion
		  /// and count the approx bit improvement until a good guess is acheived. Then test the
		  /// guess for the actual improvement. Reverse up the audit trail until it fits.

		  /// Audit trail initialisation. -1 indicates no entry.
		  memset(_pLastMbCoded, 0xFF, len * sizeof(int));
		  int lastMbPos = 0;

		  /// Repeat until the solution converges but limit it to 3 iterations for speed.
		  int prevBitCost = 0;
		  while( (bitCost > prevBitCost) && (iterations < 3) )
		  {
			prevBitCost = bitCost;
			int predR = bitCost;
			/// Make a guess by iteratively adjusting predicted rate predR
			while( (listLen > 1)&&(predR < allowedBits) )
			{
			  /// Step 2: Order the mbs in decreasing distortion.

			  /// Included all mbs from the old list except for those that have decreased down
			  /// to QP = {51}.
			  int currListLen = listLen;
			  listLen = 0;
			  for(i = 0; i < currListLen; i++)
			  {
				mb = _pMbList[i];
				if(_codec->_pMb[mb]._mbEncQP > H264V2_MAX_QP)
				  _pMbList[listLen++] = mb;
			  }//end for mb...

			  /// Bubble sort list in descending order of distortion.
			  int cnt = len;
			  while(cnt)
			  {
				cnt = 0; ///< Count how many re-orderings occur.
				for(i = 1; i < listLen; i++)
				{
				  MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i-1]]);
				  MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
				  if( pMb2->_distortion[pMb2->_mbEncQP] > pMb1->_distortion[pMb1->_mbEncQP] )
				  {
					/// Swap places.
					int tmp       = _pMbList[i-1];
					_pMbList[i-1] = _pMbList[i];
					_pMbList[i]   = tmp;
					cnt++;
				  }//end if _distortion...
				}//end for i...
			  }//end while cnt...

			  /// Step 3: Decrease the distortion of mb at the head of the ordered list to just less than the
			  /// next one in the list.
			  int mb1 = _pMbList[0]; /// Head of ordered list.
			  int mb2 = _pMbList[1]; /// Next in ordered list.
			  int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			  int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			  /// For the unusual case where the listLen == 1, set them to the same.
			  if(listLen == 1)
				d2 = d1;

			  MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

			  /// Store the current mb encoding in the audit trail lists.
			  _pLastMbCoded[lastMbPos]  = mb1;
			  _pLastMbQP[lastMbPos++]   = pMb->_mbEncQP;
			  if(lastMbPos >= len) ///< Loop around.
				lastMbPos = 0;

			  R = pMb->_rate[pMb->_mbEncQP];  ///< Remember R at this point in case the loop below does not execute.
			  predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
			  while( (pMb->_distortion[pMb->_mbEncQP] >= d2) && (pMb->_mbEncQP > H264V2_MAX_QP) && ((predR+R) <= allowedBits) )
			  {
				/// Select new QP and process.
				pMb->_mbQP = NextQPDec[pMb->_mbEncQP];
				  R = _codec->ProcessInterMbImplStd(pMb, 0, 1);
			  }//end while _distortion[]...

			  /// Add back new bits.
			  predR += R;

			}//end while listLen...

			/// Step 3: Test the new solution. On exit of the above loop, the approx
			/// bit rate is just too high and therefore the audit trail is used to reverse
			/// until it fits.

			if(lastMbPos != 0)  ///< Back up by 1.
			  lastMbPos--;
			else ///< Wrap around.
			  lastMbPos = len - 1;

			bitCost = predR;  ///< Start with the guess made above.

			while( (bitCost >= allowedBits) && (_pLastMbCoded[lastMbPos] != -1) )
			{
			  _codec->_pMb[_pLastMbCoded[lastMbPos]]._mbEncQP = _pLastMbQP[lastMbPos];
			  _pLastMbCoded[lastMbPos] = -1;  ///< Mark as used goods.
			  if(lastMbPos != 0)  ///< Back up by 1.
				lastMbPos--;
			  else ///< Wrap around.
				lastMbPos = len - 1;

			  mbSkipRun = 0;
				bitCost = 0;
				for(int mb = 0; mb < len; mb++)
				{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
				bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
				if(!pMb->_skip)
				{
				  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				  mbSkipRun = 0;
				}//end if !_skip...
				else
				  mbSkipRun++;

				}//end for mb...
			  /// Add last skip run.
			  if(mbSkipRun)
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			}//end while bitCost...

			iterations++;
		  }//end while bitCost...

		}//end if bitCost...
		else ///< All failed so mark all for min encodings and hope for the best.
		{
			  minMBIndex = 0;
		}//end else...
		*/
		///======================================================================================
		 /*
		 /// Alternating Bi-Section Algorithm.

		 Ru = Rl;  ///< Upper is now QP = {51} determined above.
		 Du = Dl;
		 Rl = 0;
		 Dl = 0;
		 mbDmax = 0;
		 qEnd   = H264V2_MAX_QP;

		 /// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		 mbSkipRun = 0;
		   for(mb = 0; mb < len; mb++)
		   {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			   pMb->_mbQP	  = H264V2_MAX_EXT_QP;
			   /// Include all macroblocks at the start.
			   pMb->_include = 1;
			   _pQl[mb]      = H264V2_MAX_EXT_QP;
			   _pQ[mb]	      = H264V2_MAX_EXT_QP;	///< Active quantiser vector is always the lower (max distortion) side.

			   /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		   /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			   Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			   if(pMb->_distortion[H264V2_MAX_EXT_QP] > Dl)
			   {
				   Dl = pMb->_distortion[H264V2_MAX_EXT_QP];
				   mbDmax = mb;	///< Mark the mb index with the peak distortion.
			   }//end if _distortion...

			   /// Early exit if this min point is still not possible. Mark all as min encodings and hope it fits.
			   if(Rl > allowedBits)
		   {
				   minMBIndex = 0;
				   break;
		   }//end if Rl...

		   }//end for mb...
		 /// Add last skip run.
		 if(mbSkipRun)
		   Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		 /// Step 2: Proceed with optimisation algorithm with QP = {51..71}
		 if(Rl < allowedBits)
		 {
			   /// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
			   /// Adjust the available bits to be epsilon below allowedBits.
			   int closeEnough = allowedBits/250;	///< 0.4%
			   if(closeEnough < 16)
				   closeEnough = 16;
			   int closeEnoughDist = 8;	///< Sqr error per macroblock.

		   /// Model based faster algorithm to improve on the bi-section method.

			   /// Modify the target rate to a close offset on the low rate side.
			   int bitTarget = allowedBits - closeEnough;

			   /// Initialisation is complete and the adapting bi-section/power model algorithm starts
			   /// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
			   /// or 2) small change in distortion when reducing the interval.
			   int done = 0;
			   while(!done)
			   {
				   int prevDmax = Dmax;

				   /// Make a prediction assuming a power law model.
	   //			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
				   /// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
	   //			if( (Dmax < Du)||(Dmax > Dl) )	///< Out of bound.
	   //				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

				   /// Encourage the descent direction by adding a decreasing factor to the
				   /// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
	   //		  Dmax += abs(Dl - Dmax)/4;

	   //			if( (Dmax < Du)||(Dmax > Dl)||(Dmax == prevDmax) )	///< Still out of bound.
					   Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

				   /// At each macroblock reduce the quant value until the distortion is lower
				   /// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector
				   /// as the previous best choice.
				   R = 0;
				   int firstMbChange = len;
				   if(invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
					   firstMbChange = 0;
			 mbSkipRun = 0;
				   for(mb = 0; mb < len; mb++)
				   {
					   MacroBlockH264* pMb = &(_codec->_pMb[mb]);

					   /// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					   _pQ[mb] = _codec->GetMbQPBelowDmaxVer3(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, FALSE);
					   R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
			   if(!pMb->_skip)
			   {
				 /// Sum of skip run and coded mb bits accumulated.
				 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				 mbSkipRun = 0;
			   }//end if !_skip...
			   else
				 mbSkipRun++;

					   /// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points
					   /// for the whole frame.

				   }//end for mb...
			 /// Add last skip run.
			 if(mbSkipRun)
			   R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

				   /// Test the stopping criteria.
				   int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
				   int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
				   int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
				   if( (rBndDiff < (4*closeEnough)) ||
						   ( (rDiff < closeEnough)||((dDiff < closeEnoughDist))) ||
				 (iterations > _codec->_interIterations) )
				 {
					   /// The new point is the preferable point to choose but if the rate is not below allowedBits
					   /// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs
			   /// must be re-processed.
					   if(R > allowedBits)
					   {
						   /// Load the lower vector as it is always below the target rate.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   R = Rl;
				 invalidated = 1;
					   }//end if R...
			   else
				 invalidated = 0;

					   /// Optimal solution is found.
					   done = 1;
				   }//end if rDiff...
				   else
				   {
					   if(allowedBits > R)	///< Inner predicted point is now lower point.
					   {
						   Dl	= Dmax;
						   Rl	= R;
						   /// pQ[] is the lower vector.
						   memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
						   invalidated = 0;
					   }//end if allowedBits...
					   else							///< Inner predicted point is now upper point.
					   {
						   Du	= Dmax;
						   Ru	= R;
						   /// pQ[] must be reset to lower vector to maintain a descent convergence.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
					   }//end else...

				   }//end else...

				   iterations++;
			   }//end while !done...

			   /// Set the macroblock QP values to their found states.
		   if(invalidated)
		   {
				 for(mb = 0; mb < len; mb++)
				 {
					 _codec->_pMb[mb]._mbQP    = _pQ[mb];
					 _codec->_pMb[mb]._mbEncQP = _pQ[mb];
				 }//end for mb...
		   }//end if invalidated...

		 }//end if Rl...
		 */
		 ///======================================================================================
		 /*
		 /// Simple Truncation Algorithm

			 /// If QP = H264V2_MAX_QP and still does not fit then a truncation process is nessecary. The truncation
			 /// is somewhere between every mb encoded with motion with zero'ed coeffs and some mbs with max QP. The
		 /// _rate[0] member of the mbs holds the min encoding and is zero for skipped. Proceed by encoding each
		 /// skip run and max QP pair per mb and then count the bits to the end.
			 R         = 0;	///< Reset.
		 mbSkipRun = 0;
			 for(mb = 0; mb < len; mb++)
			 {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Do mb encoding including motion and max QP.
			   pMb->_mbQP = H264V2_MAX_QP;
			   R += _codec->ProcessInterMbImplStd(pMb, 0, 1);  ///< Returns 0 if skipped.
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;

			 /// Add up min encodings from the next mb to the end.
			 int bitsToEnd = 0;
			 int run       = 0;
			 int mbi       = mb + 1;
			 while(mbi < len)
			 {
			   MacroBlockH264* pMbi = &(_codec->_pMb[mbi]);
			   int r = pMbi->_rate[0];
			   if(r) ///< Not skipped.
			   {
				 bitsToEnd += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(run));
				 run = 0;
			   }//end if r...
			   else
				 run++;
			   mbi++;
			 }//end while mbi...
			 if(run)
				bitsToEnd += _codec->_pHeaderUnsignedVlcEnc->Encode(run);

			 /// With this mb max QP encoded and min encoding for all remaining mbs to the end,
			 /// if it does not fit then mark it as the min encoding point and break.
			 if((R + bitsToEnd) >= allowedBits)
			 {
					   minMBIndex = mb;
					   break;
			 }//end if R...
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			 }//end for mb...
		 */
}//end DamageControl.

/** Encode the image data for Inter pictures with a Dmax criterion.
Process all macroblocks in order with a mb Dmax limit and only write the result
to the ref image space if the writeRef code is set. Bit 1 of writeRef refers to
motion compensation and bit 0 to adding the difference to the ref. The motion
estimation process with its associated data structures is assumed to have been
completed before this method is called. The macroblock obj is prepared for
coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;
	int coeffBits = 0;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  ///---------------------- Macroblock Process ------------------------------------------
	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
		{
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);
		}//end if compRef...

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this mb as the median of the neighbourhood 
		/// vectors and subtract it from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
	  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;

		/// For desperate measures when the previous encoding failed to reach the targetted rate then 
		/// a further quantisation process can be implemented here where the coeffs will be zeroed. This
		/// has been tested but is not implemented because the effectiveness is limited.
		if (_codec->_pRateCntlPFrames != NULL)
		{
			if (_codec->_pRateCntlPFrames->OutOfBounds() && _codec->_pRateCntlPFrames->LowerDistortionOverflow())
				pMb->_mbQP = H264V2_MAX_QP + 16;
		}//end if _pRateCntlPFrames...

			/// Include all macroblocks.
		pMb->_include = 1;
		/// Find QP where the mb Lum dist is just below Dmax for this mb. Count the bits for the coeffs only.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessInterMbImplStd(pMb, addRef, 3, dmax, qEnd);
		else
			_codec->ProcessInterMbImplStd(pMb, addRef, 2, dmax, qEnd);

	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplDMax::Encode.

/** Decode the Inter macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Prepare for motion compensation on a per macoblock basis.
	_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		///------------------- Motion compensation -----------------------------------------------------------
		if (pMb->_mbPartPredMode != MacroBlockH264::Inter_16x16)	///< Fixed at 16x16 mode for now.
		{
			_codec->_errorStr = "[H264V2::InterImgPlaneDecoderImplStdVer1::Decode] Only supports Inter_16x16 mode";
			return(0);
		}//end if !Inter_16x16...

		/// Compensate the vector and hope the encoder estimator ensured that
		/// all pels fall inside the image space. The motion vector was decoded
		/// from the vector differences in the ReadMacroBlockLayer() method.
		_codec->_pMotionCompensator->Compensate(lOffX, lOffY, pMb->_mvX[MacroBlockH264::_16x16], pMb->_mvY[MacroBlockH264::_16x16]);

		if (pMb->_coded_blk_pattern)
		{
			/// --------------------- Inverse Transform & Quantisation -------------------------------
			if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
				_codec->InverseTransAndQuantInter16x16MBlk(pMb, 0);

			/// --------------------- Image Storing into Ref -----------------------------------------
			/// Fill the image (difference) colour components from all the non-DC 4x4 
			/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
			MacroBlockH264::StoreBlks(pMb, _codec->_16x16, 0, 0, _codec->_8x8_0, _codec->_8x8_1, 0, 0, 0);

			/// --------------------- Add the prediction ---------------------------------------------
			/// Lum.
			_codec->_RefLum->SetOverlayDim(16, 16);
			_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
			_codec->_16x16->SetOverlayDim(16, 16);
			_codec->_16x16->SetOrigin(0, 0);
			_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add to ref Lum and leave result in ref img.
			/// Cb.
			_codec->_RefCb->SetOverlayDim(8, 8);
			_codec->_RefCb->SetOrigin(cOffX, cOffY);
			_codec->_8x8_0->SetOverlayDim(8, 8);
			_codec->_8x8_0->SetOrigin(0, 0);
			_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
			/// Cr.
			_codec->_RefCr->SetOverlayDim(8, 8);
			_codec->_RefCr->SetOrigin(cOffX, cOffY);
			_codec->_8x8_1->SetOverlayDim(8, 8);
			_codec->_8x8_1->SetOrigin(0, 0);
			_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

		}//end if _coded_blk_pattern...

	}//end for mb...

	return(1);
}//end InterImgPlaneDecoderImplStdVer1::Decode.

/*
-------------------------------------------------------------------------------------------
	Private helper methods for prediction tools.
-------------------------------------------------------------------------------------------
*/

/** Calc the median of 3 numbers.
@param x	:	1st num.
@param y	:	2nd num.
@param z	:	3rd num.
@return		: The median of x, y and z.
*/
int H264v2Codec::Median(int x, int y, int z)
{
	int min, max;

	// min = MIN(x,MIN(y,z)) and max = MAX(x,MAX(y,z)).
	if ((y - z) < 0) { min = y;	max = z; }
	else { min = z; max = y; }
	if (x < min) min = x;
	if (x > max) max = x;
	// Median.
	int result = x + y + z - min - max;

	return(result);
}//end Median.

void H264v2Codec::DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title)
{
	int i, j;

	MeasurementTable* pT = new MeasurementTable();

	int cols = pBlk->GetWidth();
	int rows = pBlk->GetHeight();

	pT->Create(cols, rows);
	for (j = 0; j < cols; j++)
	{
		pT->SetHeading(j, "");
		pT->SetDataType(j, MeasurementTable::INT);
	}//end for j...

	pT->SetTitle(title);
	for (i = 0; i < rows; i++)
		for (j = 0; j < cols; j++)
			pT->WriteItem(j, i, pBlk->Read(j, i));

	pT->Save(filename, ",", 1);

	delete pT;
}//end DumpBlock.

========== END FILE: H264v2Codec/H264v2Codec.cpp ==========

========== BEGIN FILE: H264v2Codec/H264v2Codec.h ==========
Bundle entry: 146
Original bytes: 31928
Original SHA-256: 4e17d11802b4c322825d844be1a8895ef31831d142d0c4639458515315cd13cb
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264v2Codec

TAG						: H264V2C

FILE NAME			: H264v2Codec.h

DESCRIPTION		: A 2nd generation of video codecs based on the H.264 standard
								implementation. The primary interface is ICodecv2 for access 
								and configuration.

COPYRIGHT			: (c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _H264V2CODEC_H
#define _H264V2CODEC_H

#pragma once
#include <cstddef>
#include "ICodecv2.h"
#include "ICodecInnerAccess.h"

#include "BlockH264.h"
#include "NalHeaderH264.h"
#include "SliceHeaderH264.h"
#include "SeqParamSetH264.h"
#include "PicParamSetH264.h"

#ifdef _WIN32
//#include "Windows.h"

//#define H264V2C_MICROSOFT_PARALLEL 1
#ifdef H264V2C_MICROSOFT_PARALLEL
  #include <ppl.h>
  #include <ppltasks.h>
  using namespace concurrency;
  using namespace std;
#endif
#endif

#ifdef H264V2_DUMP
/// For storing measurements during testing.
//#define H264V2_DUMP_HEADERS 1
//#define H264V2_DUMP_MB_RD_DATA 1
//#define H264V2_DUMP_TIMING 1
//#define H264V2_DUMP_FRM_RD_DATA 1
#include "MeasurementTable.h"
#endif

/// Dump filenames
#define H264V2_RATE_CNTL_PFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlPFrames.csv"
#define H264V2_RATE_CNTL_IFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlIFrames.csv"

// forward declarations
class RGBtoYUV420Converter;
class YUV420toRGBConverter;
class IBitStreamWriter;
class IBitStreamReader;
class OverlayMem2Dv2;
class IForwardTransform;
class IInverseTransform;
class VectorStructList;
class IMotionEstimator;
class IMotionCompensator;
class IMotionVectorPredictor;
class IVlcEncoder;
class IVlcDecoder;
class MacroBlockH264;
class H264MbImgCache;
class IRateControl;

class ConvYUV420_16toBGR24;
class RGBtoYUV420Converter16;

/*
===========================================================================
  Codec specific definitions.
===========================================================================
*/

/// Defined Modes of Operation for bit allocation stratergies - "mode of operation".
#define	H264V2_OPEN						        0	/// (Default) Slice QP defines the bit usage without control.
#define H264V2_MB_QP_MINMAX_ADAPTIVE	1	/// Macroblock QP is adapted to meet the frame bit target.
#define H264V2_MB_QP_AVG_ADAPTIVE	    2	/// Macroblock QP is adapted to meet an average bit target.
#define H264V2_MB_QP_DMAX_ADAPTIVE	  3	/// Macroblock QP is adapted to meet Dmax target.

/// For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE the following rate control model types may be set:
#define H264V2_RATE_CONTROL_MODEL_QUAD  0	/// Inverse quadratic model.
#define H264V2_RATE_CONTROL_MODEL_POW   1	/// Power model.
#define H264V2_RATE_CONTROL_MODEL_LOG   2	/// Inverse log model.
//#define H264V2_RATE_CONTROL_MODEL_MULTI 3	/// Combination model.

/// Seq and Pic param max encoded length.
#define	H264V2_ENC_PARAM_LEN            32

/// Use non-reversible CCIR-601 colour conversions.
//#define _CCIR601

/*
===========================================================================
  Class definition.
===========================================================================
*/
class H264v2Codec : public ICodecv2, public ICodecInnerAccess
{
  /// construction
public:
  H264v2Codec();
  virtual ~H264v2Codec();

  /// ICodecv2 Interface Implementation
public:

  int		GetParameter(const char* type, int* length, void* value);
  void	GetParameterName(int ordinal, const char** name, int* length);
  int		SetParameter(const char* type, const char* value);

  char* GetErrorStr(void) { return((char *)_errorStr); }
  int		Ready(void) { return(_codecIsOpen); }
  int		GetCompressedBitLength(void) { return((int)_bitStreamSize); }
  int		GetCompressedByteLength(void)
  {
    int x = (int)_bitStreamSize / 8; if (_bitStreamSize & 0x7) x++; return(x);
  }
  void* GetReference(int refNum) { return((void*)_pRLum); }

  void	Restart(void);
  int		Open(void);
  int		Close(void);
  int		Code(void* pSrc, void* pCmp, int codeParameter);
  int		Decode(void* pCmp, int bitLength, void* pDst);

  /// ICodecInnerAccess Interface Implementation
public:
  void* GetMember(const char* type, int* length);
  void	GetMemberName(int ordinal, const char** name, int* length);
  int		SetMember(const char* type, void* pValue);

  /// Codec parameters.
private:
  // Decode input framing: 0 = Annex-B, 1 = AVC1 four-byte lengths.
  int _inputFraming;
  int DecodeNAL(void* pNal, int nalByteLength, void* pDst);
  int DecodeInternal(void* pCmp, int bitLength, void* pDst, bool singleNal);
  /// Unique Codec identification.
  int		_idCode;																				///"codecid"
  /// The codec parameters are seperated into 2 categories. Those that are static throughout the
  /// life span of an Open()/Close() session and those that are dynamic and can be changed per
  /// picture Code()/Decode(). 

  /// -------------- Static Parameters ------------------------------------------------------ 
  /// Set before Open() and cleared at Close().

  /// Description of the source/destination image.
  int		_width;																					///< "width"
  int		_height;																				///< "height"
  int		_inColour;																			///< "incolour"
  int		_outColour;																			///< "outcolour"
  bool  _flip;                                          ///< "flip" Stores whether the internal color converters should flip the image during conversion.

  /// Modes of operation (bit allocation strategies).
  int		_modeOfOperation;																///< "mode of operation"
  int   _intraIterations;                               ///< "intra iteration limit"
  int   _interIterations;                               ///< "inter iteration limit"
  int   _timeLimitMs;                                   ///< "time limit msec"
  int   _rateControlModelType;                          ///< "rate control model type"  (Only valid for mode of operation = 2)

  /// Parameter set handling.
  int		_currSeqParam;																	///< "seq param set"
  int		_currPicParam;																	///< "pic param set"
  int		_genParamSetOnOpen;															///< "generate param set on open"
  int   _prependParamSetsToIPic;                        ///< "prepend param sets to i-pictures"

  int		_startCodeEmulationPrevention;									///< "start code emulation prevention"

  /// -------------- Dynamic Parameters ------------------------------------------------------ 
  /// Set before Code()/Decode(). Remain in effect until modified.

  /// Picture properties.
  int		_pictureCodingType;															///< "picture coding type"	(Will be interpreted into/from NAL type)
  int		_lastPicCodingType;															///< "last pic coding type"
  int		_pQuant;																				///< "quality"
  int   _minQPIntra;                                    ///< "minimum intra qp"
  int   _minQPInter;                                    ///< "minimum inter qp"

  /// I-Picture modifiers.
  int		_autoIPicture;																	///< "autoipicture"
  int		_iPictureMultiplier;														///< "ipicturemultiplier"
  int		_iPictureFraction;															///< "ipicturefraction"
  int		_iPictureDMaxMultiplier;												///< "ipicture dmax multiplier"
  int		_iPictureDMaxFraction;													///< "ipicture dmax fraction"

  int  _seqParamSetLog2MaxFrameNumMinus4;               ///< "seq param log2 max frame num minus 4"

  int  _dMax;                                           ///< "max distortion"
  int  _maxBitsPerFrame;                                ///< "max bits per frame"
  int  _numRateCntlFrames;                              ///< "num rate control frames"
  int  _rateOvershootPercent;                           ///< "rate overshoot percent"

  int _enableROIEncoding;                               ///< "enable roi encoding"

/// Attributes
private:
  /// Intermediate input/output YCbCr image mem members.
  int							_lumWidth;		/// pix width.
  int							_lumHeight;		/// pix height.
  short*					_pLum;				/// Space to compress from and decompress to.
  int							_chrWidth;
  int							_chrHeight;
  short*					_pChrU;
  short*					_pChrV;

  /// 2-D overlays for YCbCr picture mem.
  OverlayMem2Dv2*	_Lum;
  OverlayMem2Dv2*	_Cb;
  OverlayMem2Dv2*	_Cr;

  /// Reference image mem members.
  short*					_pRLum;
  short*					_pRChrU;
  short*					_pRChrV;

  /// 2-D overlays for YCbCr picture reference mem.
  OverlayMem2Dv2*	_RefLum;
  OverlayMem2Dv2*	_RefCb;
  OverlayMem2Dv2*	_RefCr;

  /// Temp 16x16 and 8x8 mem blocks for use during macroblock prediction.
  short*					_p16x16;
  OverlayMem2Dv2*	_16x16;
  short*					_p8x8_0;
  OverlayMem2Dv2*	_8x8_0;
  short*					_p8x8_1;
  OverlayMem2Dv2*	_8x8_1;

  /// Temp 4x4 blks for distortion calculations during transform and quant processes.
  BlockH264       _tmpBlk[4][4];

  /// Image caching.
  H264MbImgCache* _mbImg;

private:
  void				ResetMembers(void);
  int					CodeNonPicNALTypes(void* pCmp, int frameBitLimit);

  int					SetSeqParamSet(int index);
  int					WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int         WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int         ReadSeqParamVuiParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamVuiHrdParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					SetPicParamSet(int index, int seqRef);
  int					WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int					ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int					GetCodecParams(int picParamSet);

  int					WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);
  int					WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int         InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset);
  int         RemoveEmulationPrevention(IBitStreamReader* bsr);

  int					WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed);
  int					MacroBlockLayerBitCounter(MacroBlockH264* pMb);
  int					MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb);
  int					ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  void				ApplyLoopFilter(void);
  void				VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);
  void				HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);

  void				TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  int         GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP);
  int         TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD);

  void				TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);
  void				InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);
  void				InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);

  void				TransAndQuantInter16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  void				InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);

  int					GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode);
  void				GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  int					GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  void				GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
                                        OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr, OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr);

  int					Median(int x, int y, int z);
  static void DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title);

  /// The implementations of img plane encoders and decoders is done through a common
  /// interface and as private nested classes.
private:
  /// Common interface for img plane encoders and decoders as nested classes.
  class IImagePlaneEncoder
  {
  public:
    virtual ~IImagePlaneEncoder(void) { }
    virtual int Encode(int allowedBits, int* bitsUsed, int writeRef) = 0;
    virtual int Create(int length) { return(1); }
  };//end class IImagePlaneEncoder.
  friend class IImagePlaneEncoder;

  class IImagePlaneDecoder
  {
  public:
    virtual ~IImagePlaneDecoder(void) { }
    virtual int Decode(void) = 0;
  };//end class IImagePlaneDecoder.
  friend class IImagePlaneDecoder;

  /// Implementations of img plane encoders and decoders as nested classes of codec.

  /// Image Plane Encoders.

  class IntraImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// I-frame IDR baseline encoder.
  {
  public:
    IntraImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplStdVer1.
  friend class IntraImgPlaneEncoderImplStdVer1;

  class IntraImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< I-frame macroblock level Quant adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. 
  public:
    IntraImgPlaneEncoderImplMinMax(H264v2Codec* codec) { _codec = codec; _pQ = NULL; _pQl = NULL; _pMbList = NULL; }
    virtual ~IntraImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[3 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pMbList = _pQl + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pMbList;
  };//end class IntraImgPlaneEncoderImplMinMax.
  friend class IntraImgPlaneEncoderImplMinMax;

  class IntraImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    IntraImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplDMax.
  friend class IntraImgPlaneEncoderImplDMax;

  class InterImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// P-frame baseline encoder.
  {
  public:
    InterImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplStdVer1.
  friend class InterImgPlaneEncoderImplStdVer1;

  class InterImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< P-frame macroblock PQ adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. Uses bisection method to find optimal selection.
  public:
    InterImgPlaneEncoderImplMinMax(H264v2Codec* codec)
    {
      _codec = codec; _pQ = NULL; _pQl = NULL; _pDistortionDiff = NULL; _pMbList = NULL; _pLastMbCoded = NULL; _pLastMbQP = NULL;
    }
    virtual ~InterImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControlMvOnly(int allowedBits, int* bitsUsed);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[6 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pDistortionDiff = _pQl + length; _pMbList = _pDistortionDiff + length;
      _pLastMbCoded = _pMbList + length; _pLastMbQP = _pLastMbCoded + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pDistortionDiff;
    int*  _pMbList;
    int*  _pLastMbCoded;  ///< Audit trail.
    int*  _pLastMbQP;
  };//end class InterImgPlaneEncoderImplMinMax.
  friend class InterImgPlaneEncoderImplMinMax;

  class InterImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    InterImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplDMax.
  friend class InterImgPlaneEncoderImplDMax;

  /// Image Plane Decoders.

  class IntraImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// I-frame IDR baseline decoder.
  {
  public:
    IntraImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneDecoderImplStdVer1.
  friend class IntraImgPlaneDecoderImplStdVer1;

  class InterImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// P-frame baseline decoder.
  {
  public:
    InterImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneDecoderImplStdVer1.
  friend class InterImgPlaneDecoderImplStdVer1;

  /// Code refactoring methods.
  int   FitDistPowerModel(int rl, int dl, int ru, int du, int r);
  int   FitDistLinearModel(int rl, int dl, int ru, int du, int r);

  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP);
  void  CoeffZeroingQuantisation(MacroBlockH264* pMb);
  void  CoeffZeroingQuantisationVer2(MacroBlockH264* pMb);
  int   ProcessIntraMbImplStdMin(MacroBlockH264* pMb);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP);
  int   ProcessInterMbImplStdMin(MacroBlockH264* pMb);
  int   GetDeltaQP(MacroBlockH264* pMb);
  int   GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra);
  int   GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra);

  /// In-line methods. 

  /** Get the previous macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Previous Mb QP.
  */
  inline int GetPrevMbQP(MacroBlockH264* pMb);

  /** Get the next macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Next Mb QP.
  */
  inline int GetNextMbQP(MacroBlockH264* pMb);

  /** Get the ROI modified distortion value.
  The input distortion is modified and returned to reflect the region
  of interest bias.
  @param pMb    : Macroblock to operate on.
  @return       : Modified distortion.
  */
  inline int ROIDistortion(int mbIndex, int d)
  { if (_enableROIEncoding) return( (int)(0.5 + ((double)d * _roiMultiplier[mbIndex])) ); else return(d); }

  /** Run a high performance timer
  @return : A timer exists.
  */
  static double _cpuFreq;
  int _startTime;
  inline static int SetCounter(void) 
  {
#ifdef _WIN32
    _cpuFreq = 0.0;
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
	    return(0);
    _cpuFreq = double(li.QuadPart)/1000.0;  ///< In ms
    return(1);
#else
    return 0;
#endif
  }//end SetCounter.

  inline static double GetCounter(void)
  {
#ifdef _WIN32
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    if(_cpuFreq != 0)
      return( double(li.QuadPart)/_cpuFreq );
    else
      return(0.0);
#else
    return 0.0;
#endif
  }//end GetCounter.

/// Codec Status.
private:
	char*		_errorStr;
  char    _errorInfo[256];
	int			_codecIsOpen;
	int			_bitStreamSize;

/// Constants.
private:
	/// The id must be unique for every codec implementation.
	static const unsigned short H264V2_ID = 1003;

	/// List of all parameter names accessed via GetParameterName().
	static const int		PARAMETER_LEN;		///< "parameters".
	static const char*	PARAMETER_LIST[];	///< ...of PARAMETER_LEN.

	/// List of all member names accessed via GetMemberName().
	static const int		MEMBER_LEN;			///< "members".
	static const char*	MEMBER_LIST[];	///< ...of MEMBER_LEN.

	/// Scaling matrix for DC coeffs. Unknown reason.
	static const int dc4x4Scale[];
	static const int dc2x2Scale[];

	/// Test sampling point coordinates for Intra_16x16 and Intra_8x8 prediction mode selection.
	static const int test16X[];
	static const int test16Y[];
	static const int test16Limit[];
	static const int testZoom16X[];
	static const int testZoom16Y[];
	static const int testZoom16Len;
  static const int delta16[][2];
	static const int testZoom8[][2];
  static const int testZoom8Len;
	static const int test8X[];
	static const int test8Y[];
	static const int test8Limit[];

	static const int testPntPath16xy[][2];
	static const int testPntPath8xy[][2];

	/// Loop filter constants.
	static const int alpha[52]; 
	static const int beta[52];
	static const int indexAbS[3][52];

	/// Fast search on the macroblock distortion vs. QP curve 
	/// changes the step size.
	static const int MbStepSize[];
  static const int NextQPDec[];

  /// Motion lambda constants for TCP-like adaptation.
  static const double MVLAMBDA_MAX;
  static const double MVLAMBDA_STEP;
  static const double MVLAMBDA_MULT;
  static const double MVLAMBDA_STEADYSTATE;

/// Operational members.
private:
	/// Compressed data stream access members.
	IBitStreamWriter*			_pBitStreamWriter;
	IBitStreamReader*			_pBitStreamReader;

	/// An input colour converter.
        RGBtoYUV420Converter16 *_pInColourConverter;
	ConvYUV420_16toBGR24 *_pOutColourConverter;	

	/// 4x4 and 2x2 IT DC and AC transform filters.
	IForwardTransform* _pF4x4TLum;
	IForwardTransform* _pF4x4TChr;
	IForwardTransform* _pFDC4x4T;
	IForwardTransform* _pFDC2x2T;
	IInverseTransform* _pI4x4TLum;
	IInverseTransform* _pI4x4TChr;
	IInverseTransform* _pIDC4x4T;
	IInverseTransform* _pIDC2x2T;

	/// The motion estimator distortion is tested to	determine if an
	/// I-frame would be more appropriate for the frame. But for abs
	/// diff algorithms a different linear factor is required compared
	/// to squared error algorithms.
	int										_motionFactor;						///< Sqr Err = 4, Abs diff = 2.
	/// Auto I-frame detection test variable to hold the previous picture distortion.
	long									_prevMotionDistortion;
	///	Auto I-frame flags to indicate which macroblocks must be excluded
	/// from the decision during the motion estimation process.
	bool*									_autoIFrameIncluded;

	IMotionEstimator*			  _pMotionEstimator;				///< Selected estimator dependent on mode.
	VectorStructList*			  _pMotionEstimationResult;	///< Motion vector list generated by estimator.
	IMotionCompensator*		  _pMotionCompensator;			///< Selected compensator dependent on mode.
	VectorStructList*			  _pMotionVectors;					///< Motion vector list input to compensators.
  IMotionVectorPredictor* _pMotionPredictor;        ///< Predictor for motion vector from neighbouring mbs.

	/// Vlc encoders and decoders for use with CAVLC.
	IVlcEncoder*	_pPrefixVlcEnc;
	IVlcDecoder*	_pPrefixVlcDec;
	IVlcEncoder*	_pCoeffTokenVlcEnc;
	IVlcDecoder*	_pCoeffTokenVlcDec;
	IVlcEncoder*	_pTotalZeros4x4VlcEnc;
	IVlcDecoder*	_pTotalZeros4x4VlcDec;
	IVlcEncoder*	_pTotalZeros2x2VlcEnc;
	IVlcDecoder*	_pTotalZeros2x2VlcDec;
	IVlcEncoder*	_pRunBeforeVlcEnc;
	IVlcDecoder*	_pRunBeforeVlcDec;
	/// ... and the remaining vlc encoders and decoders.
	IVlcEncoder*	_pBlkPattVlcEnc;
	IVlcDecoder*	_pBlkPattVlcDec;
	IVlcEncoder*	_pDeltaQPVlcEnc;
	IVlcDecoder*	_pDeltaQPVlcDec = NULL;
	IVlcEncoder*	_pMbTypeVlcEnc;
	IVlcDecoder*	_pMbTypeVlcDec;
	IVlcEncoder*	_pMbIChrPredModeVlcEnc;
	IVlcDecoder*	_pMbIChrPredModeVlcDec;
	IVlcEncoder*	_pMbMotionVecDiffVlcEnc;
	IVlcDecoder*	_pMbMotionVecDiffVlcDec;
	/// Context-Aware vlc codecs for each block size.
	IContextAwareRunLevelCodec* _pCAVLC4x4;
	IContextAwareRunLevelCodec* _pCAVLC2x2;
	/// General header vlc encoders and decoders.
	IVlcEncoder*	_pHeaderUnsignedVlcEnc;
	IVlcDecoder*	_pHeaderUnsignedVlcDec;
	IVlcEncoder*	_pHeaderSignedVlcEnc;
	IVlcDecoder*	_pHeaderSignedVlcDec;

	/// Macroblocks for the image.
	int								_mbLength;	///< No. of 16 x 16 macroblocks for this image size.
	MacroBlockH264*		_pMb;				///< Base macroblock linear reference.
	MacroBlockH264**	_Mb;				///< Macroblock 2-D reference.

	/// Internal picture properties. (For now)

	/// NAL unit definition.
	NalHeaderH264		_nal;
	/// Parameter sets with their current selections that reference the parameter arrays. 
	SeqParamSetH264	_seqParam[32];
	PicParamSetH264	_picParam[255];
  int             _encSeqParamByteLen;
  unsigned char   _pEncSeqParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded seq param set. (32 bytes)
  int             _encPicParamByteLen;
  unsigned char   _pEncPicParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded pic param set. (32 bytes)

	/// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	/// control parameters to maintain a list of these references. However, in this implementation
	/// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	/// reference lists (List0) are maintained and frame number counting is consecutively incremented
	/// from the previous IDR-frame.
	int						_frameNum;				///< Used for SliceHeader._frame_num
	int						_maxFrameNum;			///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	int						_idrFrameNum;			///< Used for SliceHeader._idr_pic_id

	/// This implementation has only 1 slice for the entire frame without
	/// partitioning and therefore the slice parameters are simple.
	SliceHeaderH264	_slice;
	int							_mb_skip_run;		///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders. 
	IImagePlaneEncoder*		_pIntraImgPlaneEncoder;
	IImagePlaneEncoder*		_pInterImgPlaneEncoder;
	IImagePlaneDecoder*		_pIntraImgPlaneDecoder;
	IImagePlaneDecoder*		_pInterImgPlaneDecoder;

  /// Rate controllers and associated parameters.
  IRateControl*         _pRateCntlIFrames;
  IRateControl*         _pRateCntlPFrames;
  int                   _frameMSD;
  int                   _frameMAD;
  int                   _frameMAD_N;
  double                _predFrmMAD;
  int                   _avgBitsPerFrame;
  double                _coeffBitsPerPel;

  /// Region of Interest encoding parameters.
  double*               _roiMultiplier; ///< Multiply the distortion by a factor between 0.0..1.0 per macroblock.

  /// Motion lambda parameter for TCP-like adaptation.
  double                _mvLambda;  

#ifdef H264V2_DUMP
#ifdef H264V2_DUMP_HEADERS
  MeasurementTable _headerTable;
  int _headerTableLen;
  int _headerTablePos;
#endif
#ifdef H264V2_DUMP_MB_RD_DATA
  MeasurementTable _mbRDTable;
  int _mbRDTableLen;
  int _mbRDTablePos;
#endif
#ifdef H264V2_DUMP_TIMING
  MeasurementTable _timingTable;
  int _timingTableLen;
  int _timingTablePos;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
  MeasurementTable _frmRDTable;
  int _frmRDTableLen;
  int _frmRDTablePos;
#endif
#endif

};//H264v2Codec class.


#endif	//end _H264V2CODEC_H
========== END FILE: H264v2Codec/H264v2Codec.h ==========

========== BEGIN FILE: H264v2Codec/H264v2CodecHeader.cpp ==========
Bundle entry: 147
Original bytes: 5537
Original SHA-256: 8f8b109ec34b15e861bcaad54d02b60e24da1d4de7511c27cd58de45032184bb
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE:
 
TAG: 

FILE NAME: 

DESCRIPTION: This is a utility class to extract the header info of
a valid H264v2 bit stream.

COPYRIGHT: (c)CSIR 2007-2018 all rights reserved

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================

*/
#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#include <string.h>
#endif

#include "BitStreamReaderMSB.h"
#include "H264v2CodecHeader.h"
#include "IBitStreamReader.h"
#include "IVlcDecoder.h"
#include "ExpGolombUnsignedVlcDecoder.h"
#include "ExpGolombSignedVlcDecoder.h"

H264v2CodecHeader::H264v2CodecHeader()
{
	/// Reset all members.

	/// Internal parameters.
	_pictureCodingType			= H264v2CodecHeader::Intra;

	/// Create a bit stream reader and header vlc decoders to use during bit extraction.
	_pBitStreamReader	      = NULL;
	_pBitStreamReader       = new BitStreamReaderMSB();
  _pHeaderUnsignedVlcDec  = NULL;
	_pHeaderUnsignedVlcDec	= new ExpGolombUnsignedVlcDecoder();
  _pHeaderSignedVlcDec    = NULL;
	_pHeaderSignedVlcDec		= new ExpGolombSignedVlcDecoder();

}//end constructor.

H264v2CodecHeader::~H264v2CodecHeader()
{
	if(_pBitStreamReader != NULL)
		delete _pBitStreamReader;
	_pBitStreamReader = NULL;

	if(_pHeaderUnsignedVlcDec != NULL)
		delete _pHeaderUnsignedVlcDec;
	_pHeaderUnsignedVlcDec = NULL;

	if(_pHeaderSignedVlcDec != NULL)
		delete _pHeaderSignedVlcDec;
	_pHeaderSignedVlcDec = NULL;

}//end destructor.

/** Extract the header from the input stream.
Extract the header and pointers from the input into the
class memebers.
@param pSS		: Stream to extract from.
@param bitLen	: Bit length of input stream.
@return				: 1 = success, 0 = failed.
*/
int H264v2CodecHeader::Extract(void* pSS, int bitLen)
{
	if( (_pBitStreamReader == NULL)||(_pHeaderUnsignedVlcDec == NULL)||(_pHeaderSignedVlcDec == NULL)||(pSS == NULL) )
		return(0);

	_pBitStreamReader->SetStream(pSS, bitLen);

	int bitsSoFar = 0;

	/// The start code is a fixed 32-bit value and the NAL header is a fixed 8 bit sequence.
	if(bitLen < (8+32))
    return(0);
  
  /// Start code.
  int sc = _pBitStreamReader->Read(32);

  /// NAL
	_pBitStreamReader->Read();													///< Discard forbidden zero bit f(1).
	_nal._ref_idc		= 3 & _pBitStreamReader->Read(2);		///< u(2).
	_nal._unit_type = 31 & _pBitStreamReader->Read(5);	///< u(5).
  bitsSoFar += 8;

	switch(_nal._unit_type)
	{
		case NalHeaderH264::IDR_Slice:
			_pictureCodingType = H264v2CodecHeader::Intra;
			break;
		case NalHeaderH264::NonIDR_NoPartition_Slice:
			/// Slice without partitioning and therefore only one set of slice parameters and NAL type = Slice type.
			_pictureCodingType = H264v2CodecHeader::Inter;
			break;
		case NalHeaderH264::SeqParamSet:
			_pictureCodingType = H264v2CodecHeader::SequenceParams;
			break;
		case NalHeaderH264::PicParamSet:
			_pictureCodingType = H264v2CodecHeader::PictureParams;
			break;
		default:
      return(0);
			break;
	}//end switch _unit_type...

  return(1);
}//end Extract.

/** Get the header value by name.
This is the primary method of getting all header variables and caters 
for all variants by using strings. Care must be taken when unicode strings
are used. Typical usage:
	int	val;
	if( !Impl->Get((const unsigned char*)("width"), &val) )
		errorStr = "Header value does not exist";

@param name		:	A string of the header variable required.
@param value	:	The header value required.
@return				: 1 = found, 0 = no header exists with this name.
*/
int H264v2CodecHeader::Get(const char* name, int* value)
{
	char* p				= (char *)name;
	int		len			= (int)strlen(p);

	if(strncmp(p,"picture coding type",len) == 0)
		*value = _pictureCodingType;
	else
	{
		/// Parameter requested does not exist.
		*value = 0;
		return(0);
	}//end else...

	return(1);
}//end Get.

========== END FILE: H264v2Codec/H264v2CodecHeader.cpp ==========

========== BEGIN FILE: H264v2Codec/H264v2CodecHeader.h ==========
Bundle entry: 148
Original bytes: 4437
Original SHA-256: 7132f0f4d674cf381955f69d86de9479aef15e6cf28e1609725e7c051f37cf01
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE:
 
TAG: 

FILE NAME: 

DESCRIPTION: This is a utility class to extract the header info of
a valid H264v2 bit stream.

COPYRIGHT: (c)CSIR 2007-2018 all rights reserved

LICENSE: Software License Agreement (BSD License)

RESTRICTIONS: 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================

*/

#ifndef _H264V2CODECHEADER_H
#define _H264V2CODECHEADER_H

#pragma once

#include "IStreamHeaderReader.h"
#include "NalHeaderH264.h"

// forward declarations
class IBitStreamReader;
class IVlcDecoder;

/**
---------------------------------------------------------------------------
	Class definition.
---------------------------------------------------------------------------
*/
class H264v2CodecHeader: public IStreamHeaderReader
{
public:
	H264v2CodecHeader();
	virtual ~H264v2CodecHeader();

/// Interface implementation.
public:
	/** Extract the header from the input stream.
	Extract the header and pointers from the input into the
	class members.
	@param pSS		: Stream to extract from.
	@param bitLen	: Bit length of input stream.
	@return				: 1 = success, 0 = failed.
	*/
	int Extract(void* pSS, int bitLen);

  /** Get the header length in bits.
  @return : Length in bits.
  */
  int GetHeaderBitLength(void) { return(0); } ///< Not implemented.

	/** Get the header value by name.
	This is the primary method of getting all header variables and caters 
	for all variants by using strings. Care must be taken when unicode strings
	are used. Typical usage:
		int	val;
		if( !Impl->Get((const unsigned char*)("width"), &val) )
			errorStr = "Header value does not exist";

	@param name		:	A string of the header variable required.
	@param value	:	The header value required.
	@return				: 1 = found, 0 = no header exists with this name.
	*/
	int Get(const char* name, int* value);

	/// Implementation specific access methods.
public:
	/** Get the header info after extraction.
	The data returned is that from the last call to Extract() into the current 
	stream position.
	@return	: Requested header value.
	*/
	int GetPictureCodingType(void)								{ return(_pictureCodingType); }

/// Constants.
public:
  /// Constants for _pictureCodingType.
  static const int Intra          = 0;
  static const int Inter          = 1;
  static const int SequenceParams = 2;
  static const int PictureParams  = 3;

///	Persistant stream header data valid after an Extract() call.
protected:
	/// Internal picture properties. (For now)

	/// Main picture type of I/P/PB-frame or sequence and picture parameter sets.
	int _pictureCodingType;

	/// Global stream reader.
	IBitStreamReader*	_pBitStreamReader;
  /// Hedaer vlc decoders.
	IVlcDecoder*	    _pHeaderUnsignedVlcDec;
	IVlcDecoder*	    _pHeaderSignedVlcDec;

	/// NAL unit definition.
	NalHeaderH264		_nal;

};// end class H264v2CodecHeader.

#endif	// _H264V2CODECHEADER_H
========== END FILE: H264v2Codec/H264v2CodecHeader.h ==========

========== BEGIN FILE: H264v2Codec/new/H264v2Codec.cpp ==========
Bundle entry: 149
Original bytes: 521485
Original SHA-256: 51c1490859ec06faf12ac0e228c119d544fa3beb3d014b3b2c7ab8f42f630271
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE        : H264v2Codec

TAG           : H264V2

FILE NAME     : H264v2Codec.cpp

DESCRIPTIONS  : A 2nd generation of video codecs based on the H264 standard
				        implementation. The primary interface is ICodecv2 for access
				        and configuration.

COPYRIGHT	    : (c)CSIR 2007-2017 all rights resevered

LICENSE		    : Software License Agreement (BSD License)

RESTRICTIONS  : Redistribution and use in source and binary forms, with or without
								modification, are permitted provided that the following conditions
								are met:

								* Redistributions of source code must retain the above copyright notice,
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice,
								this list of conditions and the following disclaimer in the documentation
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used
								to endorse or promote products derived from this software without specific
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================*/

#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <cstdio>
#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include "H264v2Codec.h"

/// Macros
#include "CodecDistortionDef.h"

#include "ConvYUV420_16toRGB.h"
#include "ConvRGB24toYUV420v16FixP.h"
#include "ConvYUV420_16toRGB.h"
//#include "RGBtoYUV420Converter.h"
//#include "YUV420toRGBConverter.h"

#include "IBitStreamWriter.h"
#include "IBitStreamReader.h"
#include "OverlayMem2Dv2.h"
#include "IForwardTransform.h"
#include "IInverseTransform.h"
#include "IRunLengthCodec.h"
#include "VectorStructList.h"
#include "IMotionEstimator.h"
#include "IMotionCompensator.h"
#include "IMotionVectorPredictor.h"
#include "IVlcEncoder.h"
#include "IVlcDecoder.h"
#include "MacroBlockH264.h" 
#include "H264MbImgCache.h"
#include "IRateControl.h"

/// Implementations.
#include "BitStreamWriterMSB.h"
#include "BitStreamReaderMSB.h"

//#include "RealRGB24toYUV420CCIR601ConverterVer16.h"
//#include "RealYUV420toRGB24CCIR601ConverterVer16.h"	
//#include "RealRGB24toYUV420ConverterImpl2Ver16.h"
//#include "RealYUV420toRGB24ConverterImpl2Ver16.h"

#include "FastForward4x4ITImpl2.h"
#include "FastForward4x4ITImpl1.h"
#include "FastInverse4x4ITImpl1.h"
#include "FastForwardDC4x4ITImpl1.h"
#include "FastInverseDC4x4ITImpl1.h"
#include "FastForwardDC2x2ITImpl1.h"
#include "FastInverseDC2x2ITImpl1.h"
#include "FastForward4x4On16x16ITImpl1.h"
#include "FastInverse4x4On16x16ITImpl1.h"
#include "CAVLCH264Impl.h"
#include "CAVLCH264Impl2.h"

#include "MotionEstimatorH264ImplMultires.h"
#include "MotionEstimatorH264ImplMultiresCross.h"
#include "MotionEstimatorH264ImplCross.h"
#include "MotionEstimatorH264ImplMultiresCrossVer2.h"
#include "MotionEstimatorH264ImplFull.h"
#include "MotionEstimatorH264ImplTest.h"
#include "MotionCompensatorH264ImplStd.h"
#include "H264MotionVectorPredictorImpl1.h"


#include "PrefixH264VlcEncoderImpl1.h"
#include "PrefixH264VlcDecoderImpl1.h"
#include "CoeffTokenH264VlcEncoder.h"
#include "CoeffTokenH264VlcDecoder.h"
#include "TotalZeros4x4H264VlcEncoder.h"
#include "TotalZeros4x4H264VlcDecoder.h"
#include "TotalZeros2x2H264VlcEncoder.h"
#include "TotalZeros2x2H264VlcDecoder.h"
#include "TotalZeros2x4H264VlcEncoder.h"
#include "TotalZeros2x4H264VlcDecoder.h"
#include "RunBeforeH264VlcEncoder.h"
#include "RunBeforeH264VlcDecoder.h"
#include "ExpGolombUnsignedVlcEncoder.h"
#include "ExpGolombUnsignedVlcDecoder.h"
#include "ExpGolombSignedVlcEncoder.h"
#include "ExpGolombSignedVlcDecoder.h"
#include "ExpGolombTruncVlcEncoder.h"
#include "ExpGolombTruncVlcDecoder.h"
#include "CodedBlkPatternH264VlcEncoder.h"
#include "CodedBlkPatternH264VlcDecoder.h"

#include "RateControlImplQuad.h"
#include "RateControlImplPow.h"
#include "RateControlImplLog.h"
//#include "RateControlImplMultiModel.h"  An incomplete work in progress.

/*
---------------------------------------------------------------------------
  Codec parameter constants.
---------------------------------------------------------------------------
*/
/// Picture type definitions. Values for _pictureCodingType member.
#define H264V2_INTRA				0
#define H264V2_INTER				1
#define H264V2_SEQ_PARAM		2
#define H264V2_PIC_PARAM		3

#define H264V2_I_PIC				0
#define H264V2_P_PIC				1
#define H264V2_PB_PIC				2
#define H264V2_B_PIC				3
#define H264V2_EI_PIC				4
#define H264V2_EP_PIC				5

#define H264V2_MAX_QP							  51	///< Maximum QP value
#define H264V2_MAX_EXT_QP	          71	///< Maximum extended QP value for Inter
#define H264V2_I_MAX_EXT_QP	        85	///< Maximum extended QP value for Intra

#define H264V2_MAX_INTRA_ITERATIONS	5 	///< Default settings for a limit on optimisation iterations for slow convergence.
#define H264V2_MAX_INTER_ITERATIONS	10 

/*
---------------------------------------------------------------------------
  Colour space constants.
---------------------------------------------------------------------------
*/
#define H264V2_RGB24							0		///< 888 (Default).
#define H264V2_RGB32							1		///< 8888.
#define H264V2_RGB16							2		///< 565.

#define H264V2_YUV420P16					16	///< Planar Y, U then V (16 bits/component).
#define H264V2_YUV420P8						17	///< Planar Y, U then V (8 bits/component).

/*
--------------------------------------------------------------------------
  Macros.
--------------------------------------------------------------------------
*/
#define H264V2_CLIP31(x)	( (((x) <= 31)&&((x) >= 1))? (x) : ( ((x) < 1)? 1:31 ) )
#define H264V2_CLIP51(x)	( (((x) <= 31)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:51 ) )
#define H264V2_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

#undef	H264V2_EXACT_DMAX

#define H264V2_FAST_ABS32(x) ( ((x)^((x)>>31))-((x)>>31) )
#define H264V2_FAST_ABS16(x) ( ((x)^((x)>>15))-((x)>>15) )

/*
--------------------------------------------------------------------------
  Local constants.
--------------------------------------------------------------------------
*/
const int		H264v2Codec::PARAMETER_LEN = 36;
const char*	H264v2Codec::PARAMETER_LIST[] =
{
	"parameters",								            // 0
	"codecid",									            // 1
	"width",										            // 2
	"height",										            // 3
	"incolour",									            // 4
	"outcolour",								            // 5
  "flip",                                 // 6
	"picture coding type",			            // 7
	"last pic coding type",			            // 8
	"quality",									            // 9
	"autoipicture",							            // 10 
	"ipicturemultiplier",				            // 11
	"ipicturefraction",					            // 12
	"mode of operation",				            // 13
	"intra iteration limit",				        // 14
	"inter iteration limit",				        // 15
	"time limit msec",				              // 16
  "rate control model type",              // 17
	"seq param set",						            // 18
	"pic param set",						            // 19
	"gen param set on open",		            // 20
  "prepend param sets to i-pictures",     // 21
	"start code emulation prevention",      // 22
  "idr frame number",                     // 23
  "p frame number",                       // 24
  "seq param log2 max frame num minus 4", // 25
  "minimum intra qp",                     // 26
  "minimum intra qp",                     // 27
  "max distortion",                       // 28
  "num rate control frames",              // 29
  "max bits per frame",                   // 30
  "ipicture dmax multiplier",             // 31
  "ipicture dmax fraction",               // 32
  "rate overshoot percent",               // 33
  "enable roi encoding",                  // 34
  "input framing"                         // 35
};

const int		H264v2Codec::MEMBER_LEN = 7;
const char*	H264v2Codec::MEMBER_LIST[] =
{
	"members",									// 0
	"macroblocks",							// 1
  "reference",                // 2
	"autoiframedetectflag",			// 3
  "roi multiplier",			      // 4
  "currseqparamset",          // 5
  "currpicparamset"           // 6
};

/// Scaling is required for the DC coeffs to match the 4x4 
/// inverse IT scaling of the AC coeffs. Standard defines 
/// default Flat_4x4_16 for DC scaling.
const int H264v2Codec::dc4x4Scale[16] =
{ 16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16
};
const int H264v2Codec::dc2x2Scale[4] =
{ 16, 16,
	16, 16
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a grid defined by the method used in 
/// the Packet Video Conference Proceedings 2015 in a paper by K.T. Luhandjula and K.L. Ferguson entitled "Sampling 
/// Point Path Selection for Fast Intra Mode Prediction".
#define H264V2_16x16_PATH_LENGTH 20

const int H264v2Codec::testPntPath16xy[256][2] =
{
  {10,10},{7,5},{13,14},{3,12},{12,3},{5,8},{15,6},{7,13},{2,3},{10,1},{1,9},{12,9},{5,15},{6,2},{14,11},{9,7}, ///< 0-15
  {2,6},{14,2},{8,12},{4,4},{1,14},{11,6},{11,15},{5,0},{7,10},{0,11},{9,4},{15,10},{13,5},{4,7},{3,1},{10,13}, ///< 16-31
  {12,0},{4,11},{0,3},{8,8},{8,2},{3,14},{15,14},{6,7},{1,5},{12,12},{14,4},{3,9},{6,12},{13,7},{11,1},{0,7},   ///< 32-47
  {9,9},{5,4},{9,15},{2,10},{11,8},{4,0},{9,3},{1,12},{14,9},{7,1},{5,13},{15,1},{10,11},{0,2},{3,4},{13,15},   ///< 48-63
  {10,5},{7,14},{5,10},{12,2},{2,8},{13,11},{8,6},{0,14},{1,1},{15,8},{7,3},{9,0},{3,6},{11,12},{4,15},{14,3},  ///< 64-79
  {6,10},{14,13},{6,6},{10,7},{0,9},{4,2},{12,6},{8,14},{2,13},{2,0},{13,9},{9,8},{1,3},{6,1},{4,12},{6,4},     ///< 80-95
  {2,5},{11,11},{15,13},{1,11},{10,2},{1,4},{14,5},{8,11},{10,15},{3,8},{7,0},{0,6},{2,15},{15,0},{5,3},{14,8}, ///< 96-111
  {6,11},{12,14},{9,5},{7,7},{4,10},{9,13},{13,4},{11,9},{3,3},{4,6},{0,12},{5,1},{6,14},{14,12},{15,2},{9,10}, ///< 112-127
  {7,2},{1,7},{12,8},{4,9},{8,3},{3,13},{10,0},{12,5},{7,9},{15,7},{11,13},{7,15},{1,2},{5,6},{13,10},{11,3},   ///< 128-143
  {2,11},{15,15},{0,0},{1,15},{2,1},{10,6},{8,4},{5,12},{12,11},{11,0},{4,8},{9,8},{1,3},{6,1},{13,3},{13,13},  ///< 144-159
  {5,9},{9,12},{2,7},{15,4},{0,13},{9,14},{6,0},{3,5},{2,14},{13,6},{15,9},{8,5},{0,5},{11,10},{14,1},{3,7},    ///< 160-175
  {14,10},{8,13},{5,14},{3,2},{9,1},{1,10},{6,3},{11,7},{7,11},{12,15},{13,2},{2,9},{8,9},{10,4},{6,13},{4,1},  ///< 176-191
  {13,2},{2,9},{8,9},{10,4},{6,13},{4,1},{10,12},{0,8},{2,2},{3,11},{0,1},{10,8},{5,5},{14,7},{8,0},{0,10},     ///< 192-207
  {4,13},{6,5},{15,11},{11,2},{11,14},{8,7},{0,4},{8,10},{6,15},{13,12},{10,3},{7,4},{4,14},{1,8},{3,0},{12,7}, ///< 208-223
  {12,1},{5,11},{9,6},{4,3},{6,9},{4,5},{1,13},{15,12},{9,2},{10,14},{12,4},{1,0},{2,12},{10,9},{15,3},{5,2},   ///< 224-239
  {7,12},{14,14},{0,15},{13,8},{3,10},{14,0},{5,7},{9,11},{11,5},{1,6},{8,15},{8,1},{2,4},{12,13},{14,6},{6,8}  ///< 240-255
};
/*
const int H264v2Codec::testPntPath16xy[256][2] =
  {
	{0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},{0,12},{0,13},{0,14},{0,15}, ///< 0-15
	{1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},{1,12},{1,13},{1,14},{1,15}, ///< 16-31
	{2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},{2,12},{2,13},{2,14},{2,15}, ///< 32-47
	{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11},{3,12},{3,13},{3,14},{3,15}, ///< 48-63
	{4,0},{4,1},{4,2},{4,3},{4,4},{4,5},{4,6},{4,7},{4,8},{4,9},{4,10},{4,11},{4,12},{4,13},{4,14},{4,15}, ///< 64-79
	{5,0},{5,1},{5,2},{5,3},{5,4},{5,5},{5,6},{5,7},{5,8},{5,9},{5,10},{5,11},{5,12},{5,13},{5,14},{5,15}, ///< 80-95
	{6,0},{6,1},{6,2},{6,3},{6,4},{6,5},{6,6},{6,7},{6,8},{6,9},{6,10},{6,11},{6,12},{6,13},{6,14},{6,15}, ///< 96-111
	{7,0},{7,1},{7,2},{7,3},{7,4},{7,5},{7,6},{7,7},{7,8},{7,9},{7,10},{7,11},{7,12},{7,13},{7,14},{7,15}, ///< 112-127
	{8,0},{8,1},{8,2},{8,3},{8,4},{8,5},{8,6},{8,7},{8,8},{8,9},{8,10},{8,11},{8,12},{8,13},{8,14},{8,15}, ///< 128-143
	{9,0},{9,1},{9,2},{9,3},{9,4},{9,5},{9,6},{9,7},{9,8},{9,9},{9,10},{9,11},{9,12},{9,13},{9,14},{9,15}, ///< 144-159
	{10,0},{10,1},{10,2},{10,3},{10,4},{10,5},{10,6},{10,7},{10,8},{10,9},{10,10},{10,11},{10,12},{10,13},{10,14},{10,15}, ///< 160-175
	{11,0},{11,1},{11,2},{11,3},{11,4},{11,5},{11,6},{11,7},{11,8},{11,9},{11,10},{11,11},{11,12},{11,13},{11,14},{11,15}, ///< 176-191
	{12,0},{12,1},{12,2},{12,3},{12,4},{12,5},{12,6},{12,7},{12,8},{12,9},{12,10},{12,11},{12,12},{12,13},{12,14},{12,15}, ///< 192-207
	{13,0},{13,1},{13,2},{13,3},{13,4},{13,5},{13,6},{13,7},{13,8},{13,9},{13,10},{13,11},{13,12},{13,13},{13,14},{13,15}, ///< 208-223
	{14,0},{14,1},{14,2},{14,3},{14,4},{14,5},{14,6},{14,7},{14,8},{14,9},{14,10},{14,11},{14,12},{14,13},{14,14},{14,15}, ///< 224-239
	{15,0},{15,1},{15,2},{15,3},{15,4},{15,5},{15,6},{15,7},{15,8},{15,9},{15,10},{15,11},{15,12},{15,13},{15,14},{15,15}  ///< 240-255
  };
*/

#define H264V2_8x8_PATH_LENGTH 5

const int H264v2Codec::testPntPath8xy[64][2] =
{
  {5,5},{3,3},{7,7},{2,6},{6,1},{2,4},{7,3},{3,6},    ///< 0-7
  {1,2},{5,0},{0,4},{6,4},{2,7},{3,1},{7,5},{4,3},    ///< 8-15
  {1,3},{7,1},{4,6},{2,2},{0,7},{5,3},{5,7},{2,0},    ///< 16-23
  {3,5},{0,5},{4,2},{7,4},{6,2},{2,3},{1,0},{5,6},    ///< 24-31
  {6,0},{0,1},{4,4},{4,1},{1,7},{6,6},{3,4},{0,2},    ///< 32-39
  {6,5},{7,2},{1,4},{3,7},{6,3},{5,1},{0,3},{4,5},    ///< 40-47
  {3,2},{4,7},{1,5},{5,4},{2,1},{5,2},{0,6},{7,6},    ///< 48-55
  {3,0},{2,5},{7,0},{6,7},{1,1},{0,0},{4,0},{1,6}     ///< 56-63
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a spread out grid.
const int H264v2Codec::test16X[256] = { 3, 11,  3, 11,
									1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,
									3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,
									0,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,
									5,  9, 13,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  5,  9, 13,
									1,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  0,  3, 11, 15,  6, 14,  0,  1,  9, 15,  0,  3, 11, 15,  0,  3, 11, 15,  0,  1, 15,  6, 14,  0,  9, 15,  0,  3, 11, 15,  1,  2,  4,  6,  8, 10, 12, 14,
									2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,
									1,  5,  7,  9, 13,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13,  1,  5,  7,  9, 13,  3,  5,  7,  9, 11, 13,  1,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13 };
const int H264v2Codec::test16Y[256] = { 3,  3, 11, 11,
									1,  1,  1,  1,  5,  5,  5,  5,  9,  9,  9,  9, 13, 13, 13, 13,
									0,  0,  0,  0,  3,  3,  3,  7,  7,  7,  7,  7, 11, 11, 11, 15, 15, 15, 15, 15,
									0,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  6, 10, 10, 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14,
									0,  0,  0,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 15, 15, 15,
									0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,  8,  8,  8,  8, 10, 10, 10, 11, 11, 12, 12, 12, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
									1,  1,  1,  1,  1,  1,  1,  3,  3,  3,  3,  3,  5,  5,  5,  5,  5,  5,  5,  7,  7,  7,  7,  7,  7,  7,  9,  9,  9,  9,  9,  9,  9, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13,
									2,  2,  2,  2,  2,  4,  4,  4,  4,  4,  6,  6,  6,  6,  6,  8,  8,  8,  8,  8, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14 };
const int H264v2Codec::test16Limit[8] = { 4, 20, 40, 69, 123, 174, 219, 256 };

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a zooming square grid to be 
/// used 4 at a time where {(0,0), (0,8), (8,0), (8,8)} is added to each address in the table.
const int H264v2Codec::testZoom16X[21] =
{ 3,
  1, 5, 1, 5,
  0, 4, 0, 4,
  2, 6, 2, 6,
  0, 4, 0, 4,
  2, 6, 2, 6
};
const int H264v2Codec::testZoom16Y[21] =
{ 3,
  1, 1, 5, 5,
  0, 0, 4, 4,
  0, 0, 4, 4,
  2, 2, 6, 6,
  2, 2, 6, 6
};
const int H264v2Codec::testZoom16Len = 21;
const int H264v2Codec::delta16[4][2] = { {0,0}, {8,0}, {0,8}, {8,8} };
///< Thresholds for predicted final distortion = 20480/(256/4) = 320 (4 samples/mode completed)
#define H264V2_LUM_DISTORTION_THRESHOLD 320

const int H264v2Codec::testZoom8[5][2] = { {3,3}, {1,1}, {5,1}, {1,5}, {5,5} };
const int H264v2Codec::testZoom8Len = 5;
///< Thresholds for predicted final distortion = 10240/(128/2) = 160 (2 samples/mode completed)
#define H264V2_CHR_DISTORTION_THRESHOLD 160

/// Test sampling point coordinates for Intra_8x8 prediction mode selection.
const int H264v2Codec::test8X[64] = { 2, 5, 2, 5,
																			0, 4, 7, 0, 7, 0, 4, 7,
																			2, 5, 6, 1, 6, 0, 7, 3, 4, 3, 4, 0, 7, 1, 6, 2, 5,
																			1, 3, 0, 2, 3, 4, 5, 7, 1, 3, 4, 6, 0, 1, 2, 5, 6, 7, 1, 2, 5, 6, 1, 3, 4, 6, 0, 2, 3, 4, 5, 7, 1, 3, 6 };
const int H264v2Codec::test8Y[64] = { 2, 2, 5, 5,
																			0, 0, 0, 4, 4, 7, 7, 7,
																			0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
																			0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7 };
const int H264v2Codec::test8Limit[4] = { 4, 12, 29, 64 };

/// Loop filter constants.
const int H264v2Codec::alpha[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226, 255, 255 };
const int H264v2Codec::beta[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3,  4,  4,  4,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13,  14,  14,  15,  15,  16,  16,  17,  17,  18,  18 };
///                                           0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
const int H264v2Codec::indexAbS[3][52] = { { 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, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 8,10,11,12,13,15,17 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13,14,16,18,20,23,25} };

/// Fast search on the macroblock distortion vs. QP curve changes the step size
/// depending on the QP value.
#ifdef H264V2_EXACT_DMAX
const int H264v2Codec::MbStepSize[H264V2_MAX_QP + 1] =
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
#else
const int H264v2Codec::MbStepSize[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	 1,	 1,	 1,	 2,	 2,	 2,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 3,	 3,	 3,	 3,	 3,	 3,	 3,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		3,	 3,	 3,	 3,	 3,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		4,	 4,	 4,	 4,  1,  2,  3,  4,  1,  2,  3,  4,  1,  2,  3,  4,
//  64  65  66  67  68  69  70  71
    1,   1,  1,  1,  1,  1,  1,  1
};
#endif
const int H264v2Codec::NextQPDec[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	2,	3,	4,	5,	6,	7,	8,	 9,	10,	11,	11,	13,	13,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		15,	15,	17,	17,	19,	19,	21,	21,	23,	23,	25,	25,	27,	27,	29,	29,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		31,	31,	31,	31,	35,	35,	35,	35,	39,	39,	39,	39,	43,	43,	43,	43,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		47,	47,	47,	47, 51, 51, 51, 51, 55, 55, 55, 55, 59, 59, 59, 59,
//  64  65  66  67  68  69  70  71
		63, 63, 63, 63, 67, 68, 69, 70
};

/// CPU speed dependent high resolution timer.
double H264v2Codec::_cpuFreq = 0.0;

/// Motion lambda constants for TCP-like adaptation.
const double H264v2Codec::MVLAMBDA_MAX          = 4.0;
const double H264v2Codec::MVLAMBDA_STEP         = -0.1;
const double H264v2Codec::MVLAMBDA_MULT         = 0.5;
const double H264v2Codec::MVLAMBDA_STEADYSTATE  = 0.9;

/*
--------------------------------------------------------------------------
  Construction and destruction.
--------------------------------------------------------------------------
*/

H264v2Codec::H264v2Codec()
{
    _inputFraming = 0; // Legacy Annex-B input by default.

	ResetMembers();
}//end constructor.

void H264v2Codec::ResetMembers(void)
{
#ifdef H264V2_DUMP_HEADERS
	_headerTableLen = 300;
	_headerTable.Create(6, _headerTableLen);

	_headerTable.SetHeading(0, "NALType");
	_headerTable.SetHeading(1, "NALRefIdc");
	_headerTable.SetHeading(2, "IdrPicId");
	_headerTable.SetHeading(3, "FrmNum");
	_headerTable.SetHeading(4, "SliceType");
	_headerTable.SetHeading(5, "Qp");

	for (int j = 0; j < 6; j++)
		_headerTable.SetDataType(j, MeasurementTable::INT);

	_headerTablePos = 0;
#endif /// H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	int j;
	/// Collect macroblock R or D values for each QP for 64 macroblocks.
	_mbRDTableLen = 53;
	_mbRDTable.Create(65, _mbRDTableLen);  /// 1 for QP and 1 D value per mb

	_mbRDTable.SetHeading(0, "QP");
	_mbRDTable.SetHeading(1, "Distortion");
	for (j = 2; j < 65; j++)
		_mbRDTable.SetHeading(j, " ");

	for (j = 0; j < 65; j++)
		_mbRDTable.SetDataType(j, MeasurementTable::INT);

	/// 1st column is QP value for all mbs.
	_mbRDTable.WriteItem(0, 0, 0);
	for (j = 1; j < _mbRDTableLen; j++)
		_mbRDTable.WriteItem(0, j, j);

	_mbRDTablePos = 1;
#endif /// H264V2_DUMP_MB_RD_DATA
#ifdef H264V2_DUMP_TIMING
	_timingTableLen = 300;
	_timingTable.Create(2, _timingTableLen);

	_timingTable.SetHeading(0, "Frame");
	_timingTable.SetHeading(1, "Time (ms)");

	_timingTable.SetDataType(0, MeasurementTable::INT);
	_timingTable.SetDataType(1, MeasurementTable::INT);

	_timingTablePos = 0;
#endif /// H264V2_DUMP_TIMING

	_errorStr = "[H264v2Codec::ResetMembers] No error";
	_codecIsOpen = 0;
	_bitStreamSize = 0;

	/// Set default parameter values.
	_idCode = (int)H264V2_ID;
	_width = 176;
	_height = 144;
	_inColour = H264V2_RGB24;	///< Default to 24 bit rgb.
	_outColour = H264V2_RGB24;
	_flip = false;
	_pictureCodingType = H264V2_INTRA;
	_lastPicCodingType = H264V2_INTRA;
	_pQuant = 26;		///< Mid range [1..51].
	_minQPIntra = 16;   ///< Min QP value during mb optimisation
	_minQPInter = 4;
	_autoIPicture = 1;
	_iPictureMultiplier = 1;
	_iPictureFraction = 0;
	_iPictureDMaxMultiplier = 2;
	_iPictureDMaxFraction = 0;
	_dMax = 30000;    ///< Max distortion for all mbs with modeOfOperation = H264V2_MB_QP_DMAX_ADAPTIVE.
	_maxBitsPerFrame = 100240;   ///< This defines the max bit limit for modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_numRateCntlFrames = 12;     ///< Num of frames to do avg rate adaption over with  modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_rateOvershootPercent = 100;   ///< Percentage that the avg rate can be exceeded from frame to frame. 
	_coeffBitsPerPel = 0.0001;

	_modeOfOperation = H264V2_OPEN;
	_intraIterations = H264V2_MAX_INTRA_ITERATIONS;    ///< Intra optimisation iteration limit.
	_interIterations = H264V2_MAX_INTER_ITERATIONS;    ///< Inter optimisation iteration limit.
	_timeLimitMs = 0;  ///< Intra/inter optimisation time limit.
	_rateControlModelType = H264V2_RATE_CONTROL_MODEL_LOG;  ///< For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE.

	_currSeqParam = 0;	///< Index reference into _seqParam[32] array.
	_currPicParam = 0;	///< Index reference into _picParam[2] array.
	_genParamSetOnOpen = 1;	///< Generate the seq/pic parameter sets on the Open() call.
	_prependParamSetsToIPic = 1;  ///< Prepend a SPS and PPS NAL unit to the front of every I-Picture.

	_startCodeEmulationPrevention = 1;  ///< Enable/disable start code emulation prevention in bit stream.

	/// Work input image.
	_lumWidth = 0;
	_lumHeight = 0;
	_pLum = NULL;
	_chrWidth = 0;
	_chrHeight = 0;
	_pChrU = NULL;
	_pChrV = NULL;
	_Lum = NULL;
	_Cb = NULL;
	_Cr = NULL;
	/// Reference images.
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;
	_RefLum = NULL;
	_RefCb = NULL;
	_RefCr = NULL;

	/// Temp work mem.
	_p16x16 = NULL;
	_16x16 = NULL;
	_p8x8_0 = NULL;
	_8x8_0 = NULL;
	_p8x8_1 = NULL;
	_8x8_1 = NULL;

	/// Cache
	_mbImg = NULL;

	/// Colour converters.
	_pInColourConverter = NULL;
	_pOutColourConverter = NULL;
	/// Stream access.
	_pBitStreamWriter = NULL;
	_pBitStreamReader = NULL;
	/// IT transform filters.
	_pF4x4TLum = NULL;
	_pF4x4TChr = NULL;
	_pFDC4x4T = NULL;
	_pFDC2x2T = NULL;
	_pI4x4TLum = NULL;
	_pI4x4TChr = NULL;
	_pIDC4x4T = NULL;
	_pIDC2x2T = NULL;

	/// For motion estimation (and compensation).
	_motionFactor             = 2; ///< Default for abs diff algorithms.
	_prevMotionDistortion     = -1;
	_autoIFrameIncluded       = NULL;
	_pMotionEstimator         = NULL;
	_pMotionEstimationResult  = NULL;
	_pMotionCompensator       = NULL;
	_pMotionVectors           = NULL;
	_pMotionPredictor         = NULL;

	/// Vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = NULL;
	_pPrefixVlcDec = NULL;
	_pCoeffTokenVlcEnc = NULL;
	_pCoeffTokenVlcDec = NULL;
	_pTotalZeros4x4VlcEnc = NULL;
	_pTotalZeros4x4VlcDec = NULL;
	_pTotalZeros2x2VlcEnc = NULL;
	_pTotalZeros2x2VlcDec = NULL;
	_pRunBeforeVlcEnc = NULL;
	_pRunBeforeVlcDec = NULL;
	/// ... and the remaining vlc encoders and decoders.
	_pBlkPattVlcEnc = NULL;
	_pBlkPattVlcDec = NULL;
	_pDeltaQPVlcEnc = NULL;
	_pDeltaQPVlcDec = NULL;
	_pMbTypeVlcEnc = NULL;
	_pMbTypeVlcDec = NULL;
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	/// The CAVLC codecs.
	_pCAVLC4x4 = NULL;
	_pCAVLC2x2 = NULL;
	/// General header vlc encoders and decoders.
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// Macroblock data objects.
	_pMb = NULL;
	_Mb = NULL;

	/// Internal parameters.

	  /// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	  /// control parameters to maintain a list of these references. However, in this implementation
	  /// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	  /// reference lists (List0) are maintained and frame number counting is consecutively incremented
	  /// from the previous IDR-frame.
	_seqParamSetLog2MaxFrameNumMinus4 = 12;         ///< Range [0..12] made available as a codec parameter.
	_frameNum = 0;				  ///< Used for SliceHeader._frame_num
	_maxFrameNum = 1 << (_seqParamSetLog2MaxFrameNumMinus4 + 4);	///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	_idrFrameNum = 0;				  ///< Used for SliceHeader._idr_pic_id

	/// Slice without partitioning and therefore the slice parameters are simple. (Only one slice/frame.)
	_slice._type = SliceHeaderH264::I_Slice_All;	///< I-Slice/P-Slice.
	_slice._qp = _pQuant;	                    ///< Same as _pQuant for this implementation.
	_slice._qp_delta = 0;				                    ///< = 0 for this implementation.
	_slice._disable_deblocking_filter_idc = 0;
	_mb_skip_run = 0;				                    ///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders.
	_pIntraImgPlaneEncoder = NULL;
	_pInterImgPlaneEncoder = NULL;
	_pIntraImgPlaneDecoder = NULL;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	_pRateCntlPFrames = NULL;
	_pRateCntlIFrames = NULL;
  
  /// Region of Interest encoding.
  _roiMultiplier      = NULL;
  _enableROIEncoding  = 0; ///< Default is off.

	/// Motion vector Le Grange multiplier adaptation.
	_mvLambda = MVLAMBDA_STEADYSTATE;

	/// Timer
	_startTime = 0;

}//end ResetMembers.

H264v2Codec::~H264v2Codec()
{
	// If open then close first before exiting.
	if (_codecIsOpen)
		Close();
}//end destructor.

/*
-----------------------------------------------------------------------
  Parameter interface functions.
-----------------------------------------------------------------------
*/
int	H264v2Codec::GetParameter(const char* type, int*	length, void*	value)
{
    if(type && _stricmp(type, "input framing") == 0)
    {
        strcpy((char*)value, _inputFraming ? "avc1" : "annexb");
        *length = (int)strlen((char*)value);
        return 1;
    }


	char *p = (char *)type;
	int len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		//_itoa(_pictureCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _pictureCodingType);
	else if (strncmp(p, "last pic coding type", len) == 0)
		//_itoa(_lastPicCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _lastPicCodingType);
	else if (strncmp(p, "idr frame number", len) == 0)
		//_itoa(_idrFrameNum,(char *)value,10);
		sprintf((char *)value, "%d", _idrFrameNum);
	else if (strncmp(p, "p frame number", len) == 0)
		//_itoa(_frameNum,(char *)value,10);
		sprintf((char *)value, "%d", _frameNum);
	else if (strncmp(p, "width", len) == 0)
		//_itoa(_width,(char *)value,10);
		sprintf((char *)value, "%d", _width);
	else if (strncmp(p, "height", len) == 0)
		//_itoa(_height,(char *)value,10);
		sprintf((char *)value, "%d", _height);
	else if (strncmp(p, "incolour", len) == 0)
		//_itoa(_inColour,(char *)value,10);
		sprintf((char *)value, "%d", _inColour);
	else if (strncmp(p, "outcolour", len) == 0)
		//_itoa(_outColour,(char *)value,10);
		sprintf((char *)value, "%d", _outColour);
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = _flip ? 1 : 0;
		sprintf((char *)value, "%d", i);
	}
	else if (strncmp(p, "quality", len) == 0)
		//_itoa(_pQuant,(char *)value,10);
		sprintf((char *)value, "%d", _pQuant);
	else if (strncmp(p, "autoipicture", len) == 0)
		//_itoa(_autoIPicture,(char *)value,10);
		sprintf((char *)value, "%d", _autoIPicture);
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		//_itoa(_iPictureMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureMultiplier);
	else if (strncmp(p, "ipicturefraction", len) == 0)
		//_itoa(_iPictureFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureFraction);
	else if (strncmp(p, "codecid", len) == 0)
		//_itoa(_idCode,(char *)value,10);
		sprintf((char *)value, "%d", _idCode);
	else if (strncmp(p, "mode of operation", len) == 0)
		//_itoa(_modeOfOperation,(char *)value,10);
		sprintf((char *)value, "%d", _modeOfOperation);
	else if (strncmp(p, "intra iteration limit", len) == 0)
		//_itoa(_intraIterations,(char *)value,10);
		sprintf((char *)value, "%d", _intraIterations);
	else if (strncmp(p, "inter iteration limit", len) == 0)
		//_itoa(_interIterations,(char *)value,10);
		sprintf((char *)value, "%d", _interIterations);
	else if (strncmp(p, "time limit msec", len) == 0)
		//_itoa(_timeLimitMs,(char *)value,10);
		sprintf((char *)value, "%d", _timeLimitMs);
	else if (strncmp(p, "rate control model type", len) == 0)
		//_itoa(_rateControlModelType,(char *)value,10);
		sprintf((char *)value, "%d", _rateControlModelType);
	else if (strncmp(p, "seq param set", len) == 0)
		//_itoa(_currSeqParam,(char *)value,10);
		sprintf((char *)value, "%d", _currSeqParam);
	else if (strncmp(p, "pic param set", len) == 0)
		//_itoa(_currPicParam,(char *)value,10);
		sprintf((char *)value, "%d", _currPicParam);
	else if (strncmp(p, "generate param set on open", len) == 0)
		//_itoa(_genParamSetOnOpen,(char *)value,10);
		sprintf((char *)value, "%d", _genParamSetOnOpen);
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		//_itoa(_prependParamSetsToIPic,(char *)value,10);
		sprintf((char *)value, "%d", _prependParamSetsToIPic);
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		//_itoa(_startCodeEmulationPrevention,(char *)value,10);
		sprintf((char *)value, "%d", _startCodeEmulationPrevention);
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		//_itoa(_seqParamSetLog2MaxFrameNumMinus4,(char *)value,10);
		sprintf((char *)value, "%d", _seqParamSetLog2MaxFrameNumMinus4);
	else if (strncmp(p, "minimum intra qp", len) == 0)
		//_itoa(_minQPIntra,(char *)value,10);
		sprintf((char *)value, "%d", _minQPIntra);
	else if (strncmp(p, "minimum inter qp", len) == 0)
		//_itoa(_minQPInter,(char *)value,10);
		sprintf((char *)value, "%d", _minQPInter);
	else if (strncmp(p, "max distortion", len) == 0)
		//_itoa(_dMax,(char *)value,10);
		sprintf((char *)value, "%d", _dMax);
	else if (strncmp(p, "num rate control frames", len) == 0)
		//_itoa(_numRateCntlFrames,(char *)value,10);
		sprintf((char *)value, "%d", _numRateCntlFrames);
	else if (strncmp(p, "max bits per frame", len) == 0)
		//_itoa(_maxBitsPerFrame,(char *)value,10);
		sprintf((char *)value, "%d", _maxBitsPerFrame);
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		//_itoa(_iPictureDMaxMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxMultiplier);
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		//_itoa(_iPictureDMaxFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxFraction);
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		//_itoa(_rateOvershootPercent,(char *)value,10);
		sprintf((char *)value, "%d", _rateOvershootPercent);
  else if (strncmp(p, "enable roi encoding", len) == 0)
    sprintf((char *)value, "%d", _enableROIEncoding);
  else if (strncmp(p, "parameters", len) == 0)
		//_itoa(PARAMETER_LEN,(char *)value,10);
		sprintf((char *)value, "%d", PARAMETER_LEN);
	else
	{
		_errorStr = "[H264v2Codec::GetParameter] Read parameter not supported";
		return(0);
	}//end else...

	*length = (int)strlen((char *)value);
	return(1);

	return(0);
}//end GetParameter.

void H264v2Codec::GetParameterName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= PARAMETER_LEN))
		return;
	*name = (const char *)PARAMETER_LIST[ordinal];
	*length = (int)strlen(PARAMETER_LIST[ordinal]);

}//end GetParameterName.

int H264v2Codec::SetParameter(const char* type, const char* value)
{
    if(type && _stricmp(type, "input framing") == 0)
    {
        if(value && (_stricmp(value, "annexb") == 0 || strcmp(value, "0") == 0))
            _inputFraming = 0;
        else if(value && (_stricmp(value, "avc1") == 0 || strcmp(value, "1") == 0))
            _inputFraming = 1;
        else
        {
            _errorStr = "[H264v2Codec::SetParameter] input framing must be annexb or avc1";
            return 0;
        }
        return 1;
    }

	char *p = (char *)type;
	char *v = (char *)value;
	int  len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		_pictureCodingType = (int)(atoi(v));
	else if (strncmp(p, "idr frame number", len) == 0)
		_idrFrameNum = (int)(atoi(v));
	else if (strncmp(p, "p frame number", len) == 0)
		_frameNum = (int)(atoi(v));
	else if (strncmp(p, "width", len) == 0)
		_width = (int)(atoi(v));
	else if (strncmp(p, "height", len) == 0)
		_height = (int)(atoi(v));
	else if (strncmp(p, "incolour", len) == 0)
		_inColour = (int)(atoi(v));
	else if (strncmp(p, "outcolour", len) == 0)
		_outColour = (int)(atoi(v));
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = (atoi)(v);
		_flip = (i != 0);
	}
	else if (strncmp(p, "quality", len) == 0)
		_pQuant = (int)(atoi(v));
	else if (strncmp(p, "autoipicture", len) == 0)
		_autoIPicture = (int)(atoi(v));
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		_iPictureMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicturefraction", len) == 0)
		_iPictureFraction = (int)(atoi(v));
	else if (strncmp(p, "mode of operation", len) == 0)
		_modeOfOperation = (int)(atoi(v));
	else if (strncmp(p, "intra iteration limit", len) == 0)
		_intraIterations = (int)(atoi(v));
	else if (strncmp(p, "inter iteration limit", len) == 0)
		_interIterations = (int)(atoi(v));
	else if (strncmp(p, "time limit msec", len) == 0)
		_timeLimitMs = (int)(atoi(v));
	else if (strncmp(p, "rate control model type", len) == 0)
		_rateControlModelType = (int)(atoi(v));
	else if (strncmp(p, "seq param set", len) == 0)
		_currSeqParam = (int)(atoi(v));
	else if (strncmp(p, "pic param set", len) == 0)
		_currPicParam = (int)(atoi(v));
	else if (strncmp(p, "generate param set on open", len) == 0)
		_genParamSetOnOpen = (int)(atoi(v));
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		_prependParamSetsToIPic = (int)(atoi(v));
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		_startCodeEmulationPrevention = (int)(atoi(v));
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		_seqParamSetLog2MaxFrameNumMinus4 = (int)(atoi(v));
	else if (strncmp(p, "minimum intra qp", len) == 0)
		_minQPIntra = (int)(atoi(v));
	else if (strncmp(p, "minimum inter qp", len) == 0)
		_minQPInter = (int)(atoi(v));
	else if (strncmp(p, "max distortion", len) == 0)
		_dMax = (int)(atoi(v));
	else if (strncmp(p, "num rate control frames", len) == 0)
		_numRateCntlFrames = (int)(atoi(v));
	else if (strncmp(p, "max bits per frame", len) == 0)
		_maxBitsPerFrame = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		_iPictureDMaxMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		_iPictureDMaxFraction = (int)(atoi(v));
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		_rateOvershootPercent = (int)(atoi(v));
  else if (strncmp(p, "enable roi encoding", len) == 0)
    _enableROIEncoding = (int)(atoi(v));
  else
	{
		_errorStr = "[H264v2Codec::SetParameter] Write parameter not supported";
		return(0);
	}//end else...

	return(1);
}//end SetParameter.

/**
-----------------------------------------------------------------------
  Member interface functions.
-----------------------------------------------------------------------
*/
void* H264v2Codec::GetMember(const char* type, int* length)
{
	char*	p = (char *)type;
	int		len = (int)strlen(p);
	void* pRet = NULL;
	*length = 0;

	if (strncmp(p, "macroblocks", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_pMb;
	}
	else if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_autoIFrameIncluded;
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    *length = _mbLength;
    pRet = (void *)_roiMultiplier;
  }
  else if (strncmp(p, "reference", len) == 0)
	{
		*length = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		pRet = (void *)_pRLum;
	}
	else if (strncmp(p, "currseqparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_seqParam[_currSeqParam]));
	}
	else if (strncmp(p, "currpicparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_picParam[_currPicParam]));
	}
	else if (strncmp(p, "members", len) == 0)
	{
		int numMembers = (int)MEMBER_LEN;
		*length = 1;
		pRet = (void *)(numMembers);	///< Note that MEMBER_LEN is converted to a pointer type.
	}//end else if members...
	else
		_errorStr = "[H264v2Codec::GetMember] Read member not supported";

	return(pRet);
}//end GetMember.

void H264v2Codec::GetMemberName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= MEMBER_LEN))
		return;
	*name = (const char *)MEMBER_LIST[ordinal];
	*length = (int)strlen(MEMBER_LIST[ordinal]);

}//end GetMemberName.

int H264v2Codec::SetMember(const char* type, void* pValue)
{
	int	 i;
	char *p = (char *)type;
	int  len = (int)strlen(p);

	if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
    if (_autoIFrameIncluded == NULL) return(1);  ///< Do nothing.

    bool* pV = (bool *)pValue;
		for (i = 0; i < _mbLength; i++)
			_autoIFrameIncluded[i] = pV[i];
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    if (_roiMultiplier == NULL)
    {
      _errorStr = "[H264v2Codec::SetMember] Region of interest array not active";
      return(0);
    }//end !_roiMultiplier...

    double* pV = (double *)pValue;
    for (i = 0; i < _mbLength; i++)
      _roiMultiplier[i] = pV[i];
  }
  else
	{
		_errorStr = "[H264v2Codec::SetMember] Write member not supported";
		return(0);
	}//end else...

	return(1);
}//end SetMember.

/**
-----------------------------------------------------------------------
  Public Implementation.
-----------------------------------------------------------------------
*/
/** Open the codec for encoding/decoding.
The state of the codec and memory allocations are made in this method and are
entirely dependent on the codec parameters. Using SetParameter() all parmeters
must be set prior to calling this methods.
@return : 1 = success, 0 = failure.
*/
int H264v2Codec::Open(void)
{
	int i;

	/// If already open then close first before continuing.
	if (_codecIsOpen)
		Close();

	/// --------------- Configure Sequence & Picture parameter sets -----------------
	/// The _genParamSetOnOpen parameter determines whether or not the seq/pic params 
	/// are generated and set in this call to Open(). If the param sets are to be generated 
	/// then the SetParameters() method calls must have set the appropriate codec params 
	/// prior to calling Open()as these settings are dependent on the codec parameters.
	/// If the param sets are not to be generated then the codec params must be extracted
	/// from the seq/pic param sets.
	if (_genParamSetOnOpen)
	{
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set sequence parameter set";
			Close();
			return(0);
		}//end if !SetSeqParamSet...

		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set picture parameter set";
			Close();
			return(0);
		}//end if !SetPicParamSet...
	}//end if _genParamSetOnOpen...
	else
	{
		if (!GetCodecParams(_currPicParam))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !GetCodecParams...
	}//end else...

	/// --------------- Create encoded SPS and PPS streams ----------------------------------------
  /// Every I-Pic will have an SPS NAL, PPS NAL and an IDR NAL concatenated together in a single 
  /// stream. Create a cached param set for the current selection to use in the Code() method.
	if (_prependParamSetsToIPic)
	{
		int tempPicCodingType = _pictureCodingType;

		_pictureCodingType = H264V2_SEQ_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncSeqParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encSeqParamByteLen = GetCompressedByteLength();

		_pictureCodingType = H264V2_PIC_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncPicParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encPicParamByteLen = GetCompressedByteLength();

		/// Restore state.
		_pictureCodingType = tempPicCodingType;

	}//end if _prependParamSetsToIPic...

	  /// --------------- Alloc image memory ----------------------------------------------
	/// Create an image memory space.
	_lumWidth = _width;
	_lumHeight = _height;
	_chrWidth = _width / 2;
	_chrHeight = _height / 2;

	/// Alloc a large contiguous block with Lum first followed by ChrU then ChrV
	/// for both image blocks of input and reference.
	int lumSize = _lumWidth * _lumHeight;
	int chrSize = _chrWidth * _chrHeight;
	int imgSize = lumSize + 2 * chrSize;
	/// In/Out and ref images with primary lum at the head.
	_pLum = new short[2 * imgSize];
	if (!_pLum)
	{
		_errorStr = "[H264Codec::Open] Image memory unavailable";
		Close();
		return(0);
	}//end if !_pLum...
	  /// Place each image and colour component head pointer.
	_pChrU = &(_pLum[lumSize]);												///< End of _pLum.
	_pChrV = &(_pLum[lumSize + chrSize]);							///< End of _pChrU.
	_pRLum = &(_pLum[imgSize]);												///< End of input image.
	_pRChrU = &(_pLum[imgSize + lumSize]);							///< End of image and _pRLum.
	_pRChrV = &(_pLum[imgSize + lumSize + chrSize]);		///< End of _pRChrU.

  /// Zero the reference and the previous input image spaces. Note that the mem
	/// is contiguous.
	memset((void *)_pLum, 0, 2 * imgSize * sizeof(short));

	/// --------------- Configure the overlays to the img mem -------------------------
	/// The encoding/decoding of the residual image is performed on 4x4 blocks within
	/// each macroblock of the in/out and ref images.
	_Lum = new OverlayMem2Dv2(_pLum, _lumWidth, _lumHeight, 16, 16);
	_RefLum = new OverlayMem2Dv2(_pRLum, _lumWidth, _lumHeight, 16, 16);
	_Cb = new OverlayMem2Dv2(_pChrU, _chrWidth, _chrHeight, 8, 8);
	_RefCb = new OverlayMem2Dv2(_pRChrU, _chrWidth, _chrHeight, 8, 8);
	_Cr = new OverlayMem2Dv2(_pChrV, _chrWidth, _chrHeight, 8, 8);
	_RefCr = new OverlayMem2Dv2(_pRChrV, _chrWidth, _chrHeight, 8, 8);
	if ((_Lum == NULL) || (_RefLum == NULL) || (_Cb == NULL) ||
		(_RefCb == NULL) || (_Cr == NULL) || (_RefCr == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image and reference overlay objects";
		Close();
		return(0);
	}//end if !_Lum...

	  /// --------------- Alloc and configure prediction mem data objects ---------------------
	_p16x16 = new short[256];	///< 16x16 block for predicition operations.
	_16x16 = new OverlayMem2Dv2(_p16x16, 16, 16, 16, 16);
	_p8x8_0 = new short[64];	///< 8x8 blocks for predicition operations.
	_8x8_0 = new OverlayMem2Dv2(_p8x8_0, 8, 8, 8, 8);
	_p8x8_1 = new short[64];
	_8x8_1 = new OverlayMem2Dv2(_p8x8_1, 8, 8, 8, 8);

	if ((_p16x16 == NULL) || (_16x16 == NULL) ||
		(_p8x8_0 == NULL) || (_8x8_0 == NULL) ||
		(_p8x8_1 == NULL) || (_8x8_1 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot create prediction memory objects";
		Close();
		return(0);
	}//end if !_p16x16...

	/// ---------------- Configure Macroblock cache objects -----------------------------
	_mbImg = new H264MbImgCache();
	if (_mbImg == NULL)
	{
		_errorStr = "[H264Codec::Open] Cannot create macroblock image cache object";
		Close();
		return(0);
	}//end if !_mbImg...
	_mbImg->Create();

	/// --------------- Configure Macroblock data objects -----------------------------
	int mbWidth = _lumWidth / 16;		///< Note: Assuming mod 16 image dimensions (potential problem).
	int mbHeight = _lumHeight / 16;
	_mbLength = mbWidth * mbHeight;

	_pMb = new MacroBlockH264[_mbLength];
	_Mb = new MacroBlockH264*[mbHeight];	///< Address array.

	/// Only specified macroblocks are included in the detection of an I-frame. This
	/// flag list is used to indicate that inclusion.
	_autoIFrameIncluded = new bool[_mbLength];

	if ((_pMb == NULL) || (_Mb == NULL) || (_autoIFrameIncluded == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate macroblock data objects";
		Close();
		return(0);
	}//end if !_pMB...

	for (i = 0; i < mbHeight; i++)	///< Load the address array.
		_Mb[i] = &(_pMb[i * mbWidth]);

	/// Load the macroblock image mem 2-D offsets, indices and neighbourhood variables. There
	/// is only one slice (slice num = 0) and therefore extends from macroblock index 0..._mbLength-1.
	MacroBlockH264::Initialise(mbHeight, mbWidth, 0, _mbLength - 1, 0, _Mb);

	/// Load the flag for each macroblock that includes/excludes it from the 
	/// auto I-frame test during motion estimation. Default to include all.
	for (i = 0; i < _mbLength; i++)
		_autoIFrameIncluded[i] = 1;

	/// --------------- Configure colour converters ---------------------------------
	if (_inColour == H264V2_RGB24)
	{
		/// Encoder input.
#ifdef _CCIR601
		_pInColourConverter = new ConvRGB24toYUV420CCIR601V16Real(_width, _height);
#else
		_pInColourConverter = new ConvRGB24toYUV420v16FixP(_width, _height);
#endif

		if (_pInColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate input colour converter";
			Close();
			return(0);
		}//end if !_pInColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pInColourConverter->SetFlip(_flip);
	}//end if _inColour...

	if (_outColour == H264V2_RGB24)
	{
		/// Decoder output.
#ifdef _CCIR601
			_pOutColourConverter = new RealYUV420toRGB24CCIR601ConverterVer16(_width, _height);
#else
			_pOutColourConverter = new ConvYUV420_16toBGR24(_width, _height);	//, 128
#endif

		if (_pOutColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate output colour converter";
			Close();
			return(0);
		}//end if !_pOutColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pOutColourConverter->SetFlip(_flip);

	}//end if _outColour...

	  /// --------------- Instantiate IT filters ------------------------------------
	  /// Create Integer Transformers (IT) and their inverses for AC and DC coeffs. The
	  /// quantisers are included in the IT transform classes.
	_pF4x4TLum = new FastForward4x4ITImpl2();
	_pF4x4TChr = new FastForward4x4ITImpl2();
	_pFDC4x4T = new FastForwardDC4x4ITImpl1();
	_pFDC2x2T = new FastForwardDC2x2ITImpl1();
	_pI4x4TLum = new FastInverse4x4ITImpl1();
	_pI4x4TChr = new FastInverse4x4ITImpl1();
	_pIDC4x4T = new FastInverseDC4x4ITImpl1();
	_pIDC2x2T = new FastInverseDC2x2ITImpl1();

	if ((_pF4x4TLum == NULL) || (_pF4x4TChr == NULL) || (_pFDC4x4T == NULL) || (_pFDC2x2T == NULL) ||
		(_pI4x4TLum == NULL) || (_pI4x4TChr == NULL) || (_pIDC4x4T == NULL) || (_pIDC2x2T == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Integer Transform filter objects";
		Close();
		return(0);
	}//end if !_pF4x4TLum...

	  /// Set default modes and added scaling for IT filters.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	_pFDC2x2T->SetMode(IForwardTransform::TransformAndQuant);
	_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
	_pIDC4x4T->SetMode(IInverseTransform::TransformAndQuant);
	_pIDC2x2T->SetMode(IInverseTransform::TransformAndQuant);

	// --------------- Create the Vlc encoders and decoders --------------------------
	/// Create the vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = new PrefixH264VlcEncoderImpl1();
	_pPrefixVlcDec = new PrefixH264VlcDecoderImpl1();
	_pCoeffTokenVlcEnc = new CoeffTokenH264VlcEncoder();
	_pCoeffTokenVlcDec = new CoeffTokenH264VlcDecoder();
	_pTotalZeros4x4VlcEnc = new TotalZeros4x4H264VlcEncoder();
	_pTotalZeros4x4VlcDec = new TotalZeros4x4H264VlcDecoder();
	_pTotalZeros2x2VlcEnc = new TotalZeros2x2H264VlcEncoder();
	_pTotalZeros2x2VlcDec = new TotalZeros2x2H264VlcDecoder();
	_pRunBeforeVlcEnc = new RunBeforeH264VlcEncoder();
	_pRunBeforeVlcDec = new RunBeforeH264VlcDecoder();

	/// Vlc encoder and decoder for the coded block pattern.
	_pBlkPattVlcEnc = new CodedBlkPatternH264VlcEncoder();
	_pBlkPattVlcDec = new CodedBlkPatternH264VlcDecoder();

	/// Vlc encoder and decoder for the delta QP.
	_pDeltaQPVlcEnc = new ExpGolombSignedVlcEncoder();
	_pDeltaQPVlcDec = new ExpGolombSignedVlcDecoder();

	/// Vlc encoder and decoder for the macroblock type.
	_pMbTypeVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pMbTypeVlcDec = new ExpGolombUnsignedVlcDecoder();

	/// Vlc encoder and decoder for intra chr pred mode. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbIChrPredModeVlcEnc = _pMbTypeVlcEnc;
	_pMbIChrPredModeVlcDec = _pMbTypeVlcDec;

	/// Vlc encoder and decoder for motion vector differences. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbMotionVecDiffVlcEnc = _pDeltaQPVlcEnc;
	_pMbMotionVecDiffVlcDec = _pDeltaQPVlcDec;

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = _pMbTypeVlcEnc;
	_pHeaderUnsignedVlcDec = _pMbTypeVlcDec;
	_pHeaderSignedVlcEnc = _pDeltaQPVlcEnc;
	_pHeaderSignedVlcDec = _pDeltaQPVlcDec;

	if ((_pPrefixVlcEnc == NULL) || (_pPrefixVlcDec == NULL) ||
		(_pCoeffTokenVlcEnc == NULL) || (_pCoeffTokenVlcDec == NULL) ||
		(_pTotalZeros4x4VlcEnc == NULL) || (_pTotalZeros4x4VlcDec == NULL) ||
		(_pTotalZeros2x2VlcEnc == NULL) || (_pTotalZeros2x2VlcDec == NULL) ||
		(_pRunBeforeVlcEnc == NULL) || (_pRunBeforeVlcDec == NULL) ||
		(_pBlkPattVlcEnc == NULL) || (_pBlkPattVlcDec == NULL) ||
		(_pDeltaQPVlcEnc == NULL) || (_pDeltaQPVlcDec == NULL) ||
		(_pMbTypeVlcEnc == NULL) || (_pMbTypeVlcDec == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Vlc codec objects";
		Close();
		return(0);
	}//end if !_pPrefixVlcEnc...

	  /// Create a CAVLC encoder and decoder for each coeff block size.
	_pCAVLC4x4 = new CAVLCH264Impl();
	_pCAVLC2x2 = new CAVLCH264Impl();
	if ((_pCAVLC4x4 == NULL) || (_pCAVLC2x2 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate CAVLC codec objects";
		Close();
		return(0);
	}//end if !_pCAVLC4x4...

	  /// Attach the vlc encoders and decoders to the associated CAVLC.
	_pCAVLC4x4->SetMode(CAVLCH264Impl::Mode4x4);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcEncoder(_pTotalZeros4x4VlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcDecoder(_pTotalZeros4x4VlcDec);

	_pCAVLC2x2->SetMode(CAVLCH264Impl::Mode2x2);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcEncoder(_pTotalZeros2x2VlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcDecoder(_pTotalZeros2x2VlcDec);

	// --------------- Configure bit stream access -----------------------------------
	_pBitStreamWriter = new BitStreamWriterMSB();
	_pBitStreamReader = new BitStreamReaderMSB();
	if ((_pBitStreamWriter == NULL) || (_pBitStreamReader == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate bit stream access objects";
		Close();
		return(0);
	}//end if !_pBitStreamWriter...

	  /// --------------- Configure motion estimators -----------------------------------

	/// Create a motion vector predictor for the motion estimator to use in biasing towards
	/// the predicted vector when distortion choise is ambiguous.
	_pMotionPredictor = new H264MotionVectorPredictorImpl1(_pMb);
	if (!_pMotionPredictor)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector predictor object";
		Close();
		return(0);
	}//end if !_pMotionPredictor...

	  /// Select an appropriate motion estimator.
	int motionVectorRange;	///< In 1/4 pel units but also required for motion compensator in full pel units.
	if ((_width <= 1408) && (_height <= 1152))
		motionVectorRange = 512;	///< [-128.00 ... 127.75]
	else
		motionVectorRange = 1024;	///< [-256.00 ... 255.75]

	/// Fast less accurate estimator.
	//_pMotionEstimator = new MotionEstimatorH264ImplMultiresCrossVer2( (const void *)_pLum,	///< Multi res estimation.
	//	                                                                (const void *)_pRLum,
	//	                                                                _lumWidth,
	//	                                                                _lumHeight,
	//	                                                                motionVectorRange, ///< In 1/4 pel units.
	//	                                                                _pMotionPredictor,
	//	                                                                _autoIFrameIncluded);

	//	_pMotionEstimator = new MotionEstimatorH264ImplMultiresCross(	(const void *)_pLum,	///< Multi res estimation.
	//																																(const void *)_pRLum,
	//																																_lumWidth,
	//																																_lumHeight,
	//																																motionVectorRange, ///< In 1/4 pel units.
	//																																_autoIFrameIncluded);

  /// Cross search algorithm with partial sums as defined in the std reference implementations of H264
  _pMotionEstimator = new MotionEstimatorH264ImplCross( (const void *)_pLum,
                                                        (const void *)_pRLum,
                                                        _lumWidth,
                                                        _lumHeight,
                                                        motionVectorRange, ///< In 1/4 pel units.
                                                        _pMotionPredictor,
                                                        _autoIFrameIncluded);

  /// Slow more accurate multiresolution estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplMultires((const void *)_pLum,	///< Multi res estimation.
	//																													(const void *)_pRLum,
	//																													_lumWidth,
	//																													_lumHeight,
	//																													motionVectorRange, ///< In 1/4 pel units
	//																													_autoIFrameIncluded);

		/// Slowest full accurate estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplFull(	(const void *)_pLum,
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

		/// Test motion estimator for collecting data. Full pel only full search based estimation.
	//	_pMotionEstimator = new MotionEstimatorH264ImplTest(	(const void *)_pLum,	///< Multi res estimation.
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

	if (_pMotionEstimator != NULL)
	{
		/// Implementation specific modes.
		_pMotionEstimator->SetMode(0);	///< Auto mode.

		//_motionFactor = 2;	///< Abs diff algorithm.
		_motionFactor = 4;	///< Sqr err algorithm.

		if (!_pMotionEstimator->Create())
		{
			_errorStr = "[H264Codec::Open] Cannot create motion estimator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionEstimator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion estimator object";
		Close();
		return(0);
	}//end if else...

	  /// --------------- Configure motion compensator -----------------------------------
	  /// The motion compensator requires the range param to be in full pel units.	
	_pMotionCompensator = new MotionCompensatorH264ImplStd(motionVectorRange / 4);

	if (_pMotionCompensator != NULL)
	{
		if (!_pMotionCompensator->Create((void *)_pRLum, _lumWidth, _lumHeight, 16, 16))
		{
			_errorStr = "[H264Codec::Open] Cannot create motion compensator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionCompensator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion compensator object";
		Close();
		return(0);
	}//end if else...

	  /// Create a motion vector list to hold the decoded vectors for the compensation process.
	_pMotionVectors = new VectorStructList(VectorStructList::SIMPLE2D);
	if (!_pMotionVectors)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector list object";
		Close();
		return(0);
	}//end if !_pMotionVectors...
	if (!_pMotionVectors->SetLength(mbWidth * mbHeight)) ///< One per Mb for 16x16 vectors only.
	{
		_errorStr = "[H264Codec::Open] Insufficient mem for motion vector list";
		Close();
		return(0);
	}//end if !SetLength...

	  /// --------------- Create image plane encoders and decoders ----------------------
	  /// Select an Intra Decoder.
	_pIntraImgPlaneDecoder = new IntraImgPlaneDecoderImplStdVer1(this);
	/// Set the Inter decoder.
	_pInterImgPlaneDecoder = new InterImgPlaneDecoderImplStdVer1(this);

	/// Select an Intra and Inter Encoder depending on the mode.
	if (_modeOfOperation == H264V2_OPEN)
	{
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplStdVer1(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplStdVer1(this);
	}//end if _modeOfOperation...
	else if (_modeOfOperation == H264V2_MB_QP_MINMAX_ADAPTIVE)
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplMinMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplMinMax(this);
	}//end else...
	else	///< if((_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)||(_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE))
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplDMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplDMax(this);

		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			switch (_rateControlModelType)
			{
			case H264V2_RATE_CONTROL_MODEL_QUAD:
				_pRateCntlIFrames = new RateControlImplQuad(40.0, 20000.0);
				_pRateCntlPFrames = new RateControlImplQuad(40.0, 20000.0);
				break;
			case H264V2_RATE_CONTROL_MODEL_POW:
				_pRateCntlIFrames = new RateControlImplPow(65.0, -0.9);
				_pRateCntlPFrames = new RateControlImplPow(15000.0, -1.3);
				break;
			case H264V2_RATE_CONTROL_MODEL_LOG:
				_pRateCntlIFrames = new RateControlImplLog(0.1, 1.2);
				_pRateCntlPFrames = new RateControlImplLog(0.2, 1.4);
				break;
      /*
			case H264V2_RATE_CONTROL_MODEL_MULTI:
			  {
				  double modelParam[RateControlImplMultiModel::MODELS][2];  ///< Initial a and b model parameter per model.
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 65.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -0.9;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.1;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.2;
				  _pRateCntlIFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 15000.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -1.3;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.2;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.4;
				  _pRateCntlPFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
			  }
			break;
      */
			}//end switch _rateControlModelType...

			if ((_pRateCntlPFrames != NULL) && (_pRateCntlIFrames != NULL))
			{
				if ((!_pRateCntlPFrames->Create(_numRateCntlFrames)) || (!_pRateCntlIFrames->Create(_numRateCntlFrames)))
				{
					_errorStr = "[H264Codec::Open] Cannot create rate controllers";
					Close();
					return(0);
				}//end if !Create...
				switch (_rateControlModelType)
				{
				case H264V2_RATE_CONTROL_MODEL_QUAD:
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);  ///< Quad Abs Diff limits.
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);
					break;
				case H264V2_RATE_CONTROL_MODEL_POW:
				case H264V2_RATE_CONTROL_MODEL_LOG:
				/*case H264V2_RATE_CONTROL_MODEL_MULTI:*/
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);  ///< Multi-model Sqr Diff limits
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);
					break;
				}//end switch _rateControlModelType...
			}//end if _pRateCntlPFrames...
			else
			{
				_errorStr = "[H264Codec::Open] Cannot instantiate rate controllers";
				Close();
				return(0);
			}//end else...
		}//end if _modeOfOperation...
	}//end else...

	if ((_pIntraImgPlaneEncoder == NULL) || (_pIntraImgPlaneDecoder == NULL) ||
		(_pInterImgPlaneEncoder == NULL) || (_pInterImgPlaneDecoder == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image plane encoder and decoder objects";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...
	if ((!_pIntraImgPlaneEncoder->Create(_mbLength)) ||
		(!_pInterImgPlaneEncoder->Create(_mbLength)))
	{
		_errorStr = "[H264Codec::Open] Cannot create image plane encoders";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...

   /// --------------- Create Region of Interest members ----------------------
  _roiMultiplier = new double[_mbLength];
  if(_roiMultiplier == NULL)
  {
    _errorStr = "[H264Codec::Open] Cannot create region of interest members";
    Close();
    return(0);
  }//end if !_roiMultiplier...

   /// Fill it with 1.0 to have no effect on the distortion.
  for (i = 0; i < _mbLength; i++)
    _roiMultiplier[i] = 1.0;

  /// ---------------- Start at the beginning ----------------------------------
	_lastPicCodingType = H264V2_INTRA;
	_prevMotionDistortion = -1;
	_maxFrameNum = 1 << (_seqParam[_currSeqParam]._log2_max_frame_num_minus4 + 4);	///< Max limit (modulus) for _frameNum.
	_idrFrameNum = 0;	///< The starting I-frame counter that must then be different for every contiguous I-frame.
	Restart();

	/// Set up the optimisation time limit timer. If it does not exist then force the parameter to zero.
	if (!SetCounter())
		_timeLimitMs = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/*
	  BlockH264* pB1 = new BlockH264(4, 4);
	  BlockH264* pB2 = new BlockH264(4, 4);
	  short* pB1Mem = pB1->GetBlk();

	  /// Fill with random numbers between -250..250.
	//  srand( 34594938 );
	  srand( 2439967 );
	  for (i = 0; i < 16; i++ )
	  {
		int u = (double)rand() / (RAND_MAX + 1) * (250 - (-250))
			  + (-250);
		pB1Mem[i] = short(u);
	  }//end for i...
	  pB2->CopyBlock(pB1);  ///< Hold a copy to compare with.
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/InputBlk.csv", "Input Blk");

	  /// Forward DCT QP=1
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	  _pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTBlk.csv", "DCT Blk");
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP1Blk.csv", "DCT QP1 Blk");

	  /// Inverse DCT QP=1
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 1);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP1Blk.csv", "IQP1 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP1Blk.csv", "Output QP1 Blk");

	  /// Reload input.
	  pB1->CopyBlock(pB2);
	  /// Forward DCT QP=40
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 40);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP40Blk.csv", "DCT QP40 Blk");

	  /// Inverse DCT QP=40
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 40);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP40Blk.csv", "IQP40 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP40Blk.csv", "Output QP40 Blk");

	  delete pB2;
	  delete pB1;
	*/
	////////////////////////////////////////////////////////////////////////////////////////////////////

	_errorStr = "[H264Codec::Open] No Erorr";
	_codecIsOpen = 1;
	return(1);
}//end Open.

/** Encode one frame of pels to a compressed stream.
The input source pels in the format specified by "incolour" parameter are compressed
to the output stream. The codeParameter specifies either the max size in bits of the
pCmp buffer or the number of bits to target during the compression process. The interpretation
is determined by the "mode of operation" parameter. For SPS and PPS encoding the input
pSrc is ignored.
@param  pSrc          : Input raw pels of one complete frame.
@param  pCmp          : Output compressed stream buffer.
@param  codeParameter : Mode of operation based bit size limits.
@return               : 1 = success, 0 = failure.
*/
int	H264v2Codec::Code(void* pSrc, void* pCmp, int codeParameter)
{
	int allowedBits, bitsUsed;

	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
		return(CodeNonPicNALTypes(pCmp, codeParameter));

	if (!_codecIsOpen)
	{
		_errorStr = "[H264V2Codec::Code] Codec is not open";
		return(0);
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Code] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Mark the start time of the encoding process.
	if (_timeLimitMs)
		_startTime = (int)GetCounter();
#ifdef H264V2_DUMP_TIMING
	_startTime = (int)GetCounter();
#endif

	/// Interpret the code parameter as a frame bit limit or avg bit rate.
	int frameBitLimit = codeParameter;
	_avgBitsPerFrame = codeParameter;
	double avgBppRate = (double)(_avgBitsPerFrame) / (double)(_lumWidth*_lumHeight);  ///< Bit rate in bits per pel.
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		frameBitLimit = _maxBitsPerFrame; ///< Bit limit must be made sufficiently large for variations in the buffered rate per frame.

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	_bitStreamSize = 0;

	/// Reset the stream writer with the frame bit limit. 
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Only IDR and P pictures are supported.
	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
	{
		_errorStr = "[H264v2Codec::Code] Picture coding type not supported";
		return(0);
	}//end if !H264V2_INTRA...

   ///-------------- Colour Space Conversion -----------------------------------------------
  if (_inColour == H264V2_YUV420P16)	      ///< The natural colour space of the encoder with type = short.
		memcpy((void *)_pLum, (const void *)pSrc, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_inColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			_pLum[i] = (short)((unsigned char *)pSrc)[i];
	}//end if H264V2_YUV420P8...
	else
		_pInColourConverter->Convert((void *)pSrc, (void *)_pLum, (void *)_pChrU, (void *)_pChrV);

  ///-------------- Motion Estimation -----------------------------------------------
  /// Motion estimation is used to determine if an IDR frame should be inserted.
	if (_pictureCodingType == H264V2_INTER)
	{
		/// Motion estimation.
		long motionDistortion = 0;

		/// The estimator implementation was chosen in Open() depending on the mode selected.
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			/// Motion vector lambda adaptation in this mode uses a TCP-like algorithm. Note that it uses the most recent past
      /// P-frame rate control results applied to this P-frame.
			double deltaLambda = 0.0;
			if (_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->UpperDistortionOverflow())
				deltaLambda = MVLAMBDA_MULT*(MVLAMBDA_MAX - _mvLambda);
			else if ((_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->LowerDistortionOverflow()) || (_mvLambda > MVLAMBDA_STEADYSTATE))
				deltaLambda = MVLAMBDA_STEP;
			_mvLambda += deltaLambda;
			if (_mvLambda < 0.0) _mvLambda = 0.0;

			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion, (void *)(&_mvLambda)));
		}//end if H264V2_MB_QP_AVG_ADAPTIVE...
		else
			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion));

		/// The estimation results are processed into an encoded structure list. A 
		/// decision is made on the type of encoding as predictive or basic and 
		/// returns the selection. The _Motion member reflects the choice.

		/// Auto I-picture detection.
		if (_autoIPicture && (_prevMotionDistortion != -1)) ///< Previous frame was not an I-Picture.
		{
			/// Test for an I-picture.
			if (motionDistortion > (_motionFactor * _prevMotionDistortion))
				_pictureCodingType = H264V2_INTRA;
		}///end if _prevMotionDistortion...

		_prevMotionDistortion = motionDistortion;

		/// Force an I-picture if frame counter has wraped around in the modulus calculation.
		if (_frameNum == 0)
			_pictureCodingType = H264V2_INTRA;

	}//end if H264V2_INTER...

	/// The motion estimation process is used to determine if this picture
	/// should rather be coded as an IDR picture. Therefore the INTRA 
	/// picture type coding is done afterwards. 

  ///-------------- Pre-encoding rate control ---------------------------------
  if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
  {
    /// Reset global frame accumulator.
    _frameMSD = 0;
    _frameMAD = 0;
    _frameMAD_N = 0;
    _predFrmMAD = 0.0;

    if (_pictureCodingType == H264V2_INTER)
    {
      /// Distortion is modified only when there is valid data in the rate control model. 
      /// Otherwise it remains at the previous frame's settings.
      if (_pRateCntlPFrames->ValidData())
      {
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlPFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      if (_pRateCntlIFrames->ValidData())
      {
        /// Readjust average frame bits with multiplier.fraction factor.
        avgBppRate = (avgBppRate * (double)_iPictureMultiplier) + ((avgBppRate * (double)_iPictureFraction) / 10.0);
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlIFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end else if H264V2_INTRA...
  }//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Headers and Preparation  ---------------------------------
  /// For INTRA pictures and before any encoding begins readjust the 
	/// allowable bits based on the I-picture multiplier parameters.
	if (_pictureCodingType == H264V2_INTRA)
	{
		/// Continuously divide by 10 until in the range 0..9.
		while (_iPictureFraction > 10)
			_iPictureFraction = (_iPictureFraction / 10);
		/// Readjust frame bits with multiplier.fraction factor. Protect against excessively large bit limits that result in integer wrapping.
		int prior = frameBitLimit;
		frameBitLimit = (frameBitLimit * _iPictureMultiplier) + ((frameBitLimit * _iPictureFraction) / 10);
		if (frameBitLimit < prior) frameBitLimit = prior;
		_pBitStreamWriter->SetStreamBitSize(frameBitLimit);
		/// New bit limit setting.
		bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	  /// Reset the frame number for I-pics.
		_frameNum = 0;

		/// Prepend SPS and PPS to the I-picture.
		if (_prependParamSetsToIPic)
		{
			allowedBits = bitLimit - _bitStreamSize;
			int paramTotBitLen = 8 * (_encSeqParamByteLen + _encPicParamByteLen);
			if (allowedBits < paramTotBitLen)
			{
				_errorStr = "[H264V2Codec::Code] Cannot prepend SPS and PPS to I-Picture stream";
				return(0);
			}//end if allowedBits...

			/// Write the pre-encoded SPS to the stream.
			int i;
			for (i = 0; i < _encSeqParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncSeqParam[i]);

			/// Write the pre-encoded PPS to the stream.
			for (i = 0; i < _encPicParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncPicParam[i]);

			_bitStreamSize += paramTotBitLen;

		}//end if _prependParamSetsToIPic...
	}//end if H264V2_INTRA...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::Code] Cannot write start code to stream";
		return(0);
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Define the NAL unit header based on the seleceted picture coding type. The final NAL type
	/// is only known at this point in the process.
	if (_pictureCodingType == H264V2_INTER)
	{
		_nal._ref_idc = 2;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::NonIDR_NoPartition_Slice;
	}//end if H264V2_INTER...
	else	///< if(_pictureCodingType == H264V2_INTRA)
	{
		_nal._ref_idc = 3;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::IDR_Slice;
	}//end else...

	  /// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice header layer with its header flags to
	/// the stream. There is only one slice so the header, macroblocks (slice
	/// data) and tail may be coded in a linear order.
	_slice._frame_num = _frameNum;
	_slice._idr_pic_id = _idrFrameNum;
	/// Force the image plane encoders to use _pQuant as the slice qp and therefore the
	/// slice header is determined before encoding and may be added to the bit stream here.
	_slice._qp = _pQuant;
	_slice._qp_delta = _slice._qp - (_picParam[_currPicParam]._pic_init_qp_minus26 + 26);
	_slice._pic_parameter_set_id = _currPicParam;
	/// Baseline profile only has two slice types and in this implementation they are
	/// used for the entire frame/picture.
	if (_pictureCodingType == H264V2_INTER)
		_slice._type = SliceHeaderH264::P_Slice_All;
	else
		_slice._type = SliceHeaderH264::I_Slice_All;

	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteSliceLayerHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Encode the entire picture. The plane encoders do not write to the stream
	/// but do require to know the available bits. Allowance is made for the single
	/// trailing bit.
	allowedBits = bitLimit - _bitStreamSize - 1;

	///-------------- Encoding process ---------------------------------
	if (_pictureCodingType == H264V2_INTRA)
	{
		_prevMotionDistortion = -1;
		Restart(); ///< Reset the loop for I-picture.

			/// The encoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of slices and their macroblocks.
		if (!_pIntraImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 1))
			return(0);	///< An error has occured.
	}//end if H264V2_INTRA...
	else if (_pictureCodingType == H264V2_INTER)
	{
		/// The encoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 3))
			return(0);	///< An error has occured.
	}//end else H264V2_INTER...

  ///-------------- Write to stream ---------------------------------
	/// Write (concatinate) the macroblock layer (slice data) with its header 
	/// flags to the stream.
	runOutOfBits = WriteSliceDataLayer(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice trailing bits to the stream. This is a min
  /// of 1 bit + zero bits to the end of the byte boundary.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Prevent start code emulation within the coded bit stream. The extra byte added
	/// to prevent the emulation is not counted as part of the bit written.
	if (_startCodeEmulationPrevention)
	{
		int offset = 0;
		if ((_pictureCodingType == H264V2_INTRA) && (_prependParamSetsToIPic))
			offset = _encSeqParamByteLen + _encPicParamByteLen;

		_bitStreamSize += InsertEmulationPrevention(_pBitStreamWriter, offset);
	}//end if _startCodeEmulationPrevention...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	///-------------- Post-encoding rate control ---------------------------------
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
	{
		/// Measured mean abs and squared difference. Members were set per mb in the ProcessInterMbImplStd() method.
		double frmMAD = (double)(_frameMAD);
		double frmMSD = (double)(_frameMSD);
		if (_frameMAD_N)
		{
			frmMAD = frmMAD / (double)(_frameMAD_N);
			frmMSD = frmMSD / (double)(_frameMAD_N);
		}//end if _frameMAD_N...

		IRateControl* lclRateCntrl = _pRateCntlPFrames; ///< Default to P-Frames.
		if (_pictureCodingType == H264V2_INTER)
		{
			/// Reset the P-Frame RDO model after I-Frames.
	    //if(_lastPicCodingType == H264V2_INTRA)
	    //  _pRateCntlPFrames->Reset();
		}//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      /// Force a rest of the mean difference buffer of P-frames to reflect the scene change.
//      _pRateCntlPFrames->Reset(0.0, 0.0, 0.0, frmMSD, frmMAD);

      /// Inform the P-frame rate controller that things will different now that their is probably a new scene sequence.
      _pRateCntlPFrames->SignalSceneChange(frmMSD, frmMAD);  
      lclRateCntrl = _pRateCntlIFrames;
    }//end else if H264V2_INTRA...

		/// Store total rate, coeff rate, distortion, mean difference (and header rate).
		double rateBpp = (double)_bitStreamSize / (double)(_lumWidth*_lumHeight);
    if(_rateControlModelType == H264V2_RATE_CONTROL_MODEL_QUAD)
		  lclRateCntrl->StoreMeasurements(rateBpp, _coeffBitsPerPel, (double)(_dMax), frmMSD, frmMAD);
    else
      lclRateCntrl->StoreMeasurements(rateBpp, rateBpp, (double)(_dMax), frmMSD, frmMAD);

	}//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Prepare for next frame ---------------------------------

	/// Any param changes required for the next picture encoding are done here.
	/// INTER pictures by default follow INTRA pictures.
	int tmpLastPicCodingType = _lastPicCodingType;
	_lastPicCodingType = _pictureCodingType;
	if (_pictureCodingType == H264V2_INTRA)
	{
		_pictureCodingType = H264V2_INTER;
		/// The IDR-frame num is by default 0 unless the previous frame was also an IDR-frame.
		/// In this case, it toggles between 1 and 0. The H.264 standard only requires
		/// consecutive IDR-frames to be different ITU-T Recommendation H.264 (03/2005) page 77.
		if ((tmpLastPicCodingType == H264V2_INTRA) && (_idrFrameNum == 0))
			_idrFrameNum = 1;
		else
			_idrFrameNum = 0;
	}//end if H264V2_INTRA...
	else
		_idrFrameNum = 0;

	///< Increment the frame number relative to the last I-frame for the next frame.
	_frameNum = (_frameNum + 1) % _maxFrameNum;

#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos < _timingTableLen)
	{
		_timingTable.WriteItem(0, _timingTablePos, _timingTablePos);
		_timingTable.WriteItem(1, _timingTablePos, (int)GetCounter() - _startTime);
		_timingTablePos++;
	}//end if _timingTablePos...
#endif

	return(1);
}//end Code.

/** Decode the compresed frame into raw pel samples.
The input types are a compressed picture IDR or P NAL unit, a SPS, a PPS or a concatenated
SPS, PPS and compressed picture. The output is the raw picture pels in the format specified
by the "outcolour" codec parameter.
@param  pCmp      : Compressed stream.
@param  bitLength : Length in bits of pCmp.
@param  pDst      : Raw pel output.
@return           : 1 = success, 0 = failure.
*/
int H264v2Codec::Decode(void* pCmp, int bitLength, void* pDst)
{
    if(!_inputFraming)
        return DecodeInternal(pCmp, bitLength, pDst, false);

    // AVC1 input: one complete sample with four-byte big-endian NAL lengths.
    // Validate the entire framing before the existing unescaper mutates payload.
    if(!pCmp || bitLength <= 0 || (bitLength & 7))
    {
        _errorStr = "[H264v2Codec::Decode] Invalid AVC1 sample length";
        return 0;
    }
    unsigned char* input = (unsigned char*)pCmp;
    const int bytes = bitLength / 8;
    int pos = 0;
    bool sawPicture = false;
    while(pos < bytes)
    {
        if(bytes - pos < 4)
        {
            _errorStr = "[H264v2Codec::Decode] Truncated AVC1 length prefix";
            return 0;
        }
        const unsigned int n = ((unsigned int)input[pos] << 24) |
            ((unsigned int)input[pos+1] << 16) |
            ((unsigned int)input[pos+2] << 8) | input[pos+3];
        pos += 4;
        if(n == 0 || n > (unsigned int)(bytes - pos))
        {
            _errorStr = "[H264v2Codec::Decode] Invalid AVC1 NAL length";
            return 0;
        }
        const unsigned int type = input[pos] & 31;
        if((input[pos] & 0x80) || sawPicture ||
           (type != 1 && type != 5 && type != 7 && type != 8))
        {
            _errorStr = "[H264v2Codec::Decode] Unsupported AVC1 NAL order or type";
            return 0;
        }
        if(type == 1 || type == 5)
            sawPicture = true;
        pos += (int)n;
    }
    if(sawPicture && (!_codecIsOpen || !pDst))
    {
        _errorStr = "[H264v2Codec::Decode] Picture requires an open codec and output buffer";
        return 0;
    }

    pos = 0;
    while(pos < bytes)
    {
        const unsigned int n = ((unsigned int)input[pos] << 24) |
            ((unsigned int)input[pos+1] << 16) |
            ((unsigned int)input[pos+2] << 8) | input[pos+3];
        pos += 4;
        if(!DecodeNAL(input + pos, (int)n, pDst))
            return 0;
        // Use the original length, not the shortened unescaped payload size.
        pos += (int)n;
    }
    return 1;
}

// Private helper. Prefix-free input starts at the NAL header, not the payload.
int H264v2Codec::DecodeNAL(void* pNal, int nalByteLength, void* pDst)
{
    return DecodeInternal(pNal, nalByteLength * 8, pDst, true);
}

int H264v2Codec::DecodeInternal(void* pCmp, int bitLength, void* pDst, bool singleNal)
{
	int	runOutOfBits = 0;
	int frameBitSize = bitLength;
	int bitsUsed = 0;
	int ret = 1;
	int moreNonPicNALUnits = 1;

	/// Set the bit stream access. The bit stream reader and related objects are instantiated within 
	/// Open() and is therefore not available for non-picture NAL types. They are temporarily created 
	/// for these other NAL types.
	_bitStreamSize = bitLength;
	if (!_codecIsOpen)
	{
		_pBitStreamReader = new BitStreamReaderMSB();
		_pHeaderUnsignedVlcDec = new ExpGolombUnsignedVlcDecoder();
		_pHeaderSignedVlcDec = new ExpGolombSignedVlcDecoder();		
	}//end if !_codecIsOpen...
		// JFO: function cannot continue when one of 3 pointers is NULL
        if ((_pBitStreamReader == NULL) || (_pHeaderUnsignedVlcDec == NULL) || (_pHeaderSignedVlcDec == NULL))
	{
	  _errorStr = "[H264Codec::Decode] Cannot instantiate stream reader and vlc objects";
	  ret = 0;
	  goto H264V2_D_CLEAN_MEM;
	}//end if !_pBitStreamReader...


	  /// Set the stream reader.
	_pBitStreamReader->SetStream(pCmp, bitLength);

	/// Typically in-band SPS and PPS are prepended to IDR frames. Therefore keep decoding until all
	/// non-picture NAL types are decoded. If the frameBitSize indicates at least 4 more bytes (32 bits)
	/// then we assume there is another NAL to be decoded.
	while (moreNonPicNALUnits)
	{
        if(!singleNal)
        {
		/// Extract the start code 0x00000001 from the stream.
		int startCode = _pBitStreamReader->Read(32);
		if (startCode != 1)
		{
			_errorStr = "[H264Codec::Decode] Cannot extract start code from stream";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if frameBitSize...
		frameBitSize -= 32;

        }

		/// Get the NAL header encodings off the bit stream to determine the picture coding type..
		runOutOfBits = ReadNALHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
		frameBitSize -= bitsUsed;
		if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		{
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if runOutOfBits...

		/// NAL to coding type conversion.
		switch (_nal._unit_type)
		{
		case NalHeaderH264::IDR_Slice:
			_pictureCodingType = H264V2_INTRA;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::NonIDR_NoPartition_Slice:
			/// Slice without partitioning and therefore only one set of slice parameters and NAL type = Slice type.
			_pictureCodingType = H264V2_INTER;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::SeqParamSet:
		case NalHeaderH264::PicParamSet:
		{
			int changed = 1;  ///< Indicate if the decoded params for this index have changed. Assume they have changed as the default.
			if (_nal._unit_type == NalHeaderH264::SeqParamSet)
			{
				_pictureCodingType = H264V2_SEQ_PARAM;
				/// Read the seq param set off the stream.
				runOutOfBits = ReadSeqParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currSeqParam, &changed);
			}//end if SeqParamSet...
			else ///< if(_nal._unit_type == NalHeaderH264::PicParamSet)
			{
				_pictureCodingType = H264V2_PIC_PARAM;
				/// Read the pic param set off the stream.
				runOutOfBits = ReadPicParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currPicParam, &changed);
				if (!runOutOfBits)
					_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
			}//end else...
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

			/// Read the trailing bits off the stream.
			runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

	/// If the codec is in the open state then any change in sequence or picture param set requires the
	/// codec to be restarted with these new sets. But the bit stream must be preserved and restored 
	/// after the call to Open().
			if (_codecIsOpen)
			{
				if (changed)
				{
					/// Preserve the bitstream
					IBitStreamReader* pTmpBitStreamReader = new BitStreamReaderMSB();
					pTmpBitStreamReader->Copy(_pBitStreamReader);

					int tmpPicCodingType = _pictureCodingType; ///< Store the coding type.

					_genParamSetOnOpen = 0; ///< Must be off if the new param sets are to be used.
					if (!Open())
					{
						delete pTmpBitStreamReader;
						ret = 0;
						goto H264V2_D_CLEAN_MEM;
					}//end if !Open...

					/// Restore the picture coding type.
					_pictureCodingType = tmpPicCodingType;
					/// Restore the bitstream.
					_pBitStreamReader->Copy(pTmpBitStreamReader);
					delete pTmpBitStreamReader;
				}//end if changed...

			}//end if _codecIsOpen...

#ifdef H264V2_DUMP_HEADERS
			if (_headerTablePos < _headerTableLen)
			{
				_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
				_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
				_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
				_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
				_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
				_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

				_headerTablePos++;
			}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

			if (singleNal || frameBitSize < 32) ///< No more units in this call.
			{
				moreNonPicNALUnits = 0;
				if (_codecIsOpen)
					return(1);
				else
				{
					/// Clean up the mem.
					ret = 1;
					goto H264V2_D_CLEAN_MEM;
				}//end else...
			}//end if frameBitSize...

		};//end SeqParamSet and PicParamSet block...
		break;
		default:
			_errorStr = "[H264v2Codec::Decode] NAL unit type not supported";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
			break;
		}//end switch _unit_type...
	}//end while moreNonPicNALUnits...

	  /// Only IDR and P pictures are decoded from here and the codec must be open.
	if (!_codecIsOpen)
	{
		_errorStr = "[H264v2Codec::Decode] Codec is not open";
		ret = 0;
		goto H264V2_D_CLEAN_MEM;
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Decode] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Remove prevention of start code emulation codes within the coded bit stream.
	if (_startCodeEmulationPrevention)
		frameBitSize -= RemoveEmulationPrevention(_pBitStreamReader);

	/// Get the slice header encodings off the bit stream. As this implementation 
	/// has only one slice, the slice header, slice data (macroblocks) and the 
	/// slice trailing bits can be decoded in linear order.
	runOutOfBits = ReadSliceLayerHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);
	/// Load frame counter members from the decoded slice header.
	_frameNum = _slice._frame_num;
	_idrFrameNum = _slice._idr_pic_id;
	/// Load the picture and sequence parameter set references.
	_currPicParam = _slice._pic_parameter_set_id;
	_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
	/// There is only one slice so the quant parameter is picture quant + the delta slice quant.
	_slice._qp = _picParam[_currPicParam]._pic_init_qp_minus26 + 26 + _slice._qp_delta;
	_pQuant = _slice._qp;

#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos < _headerTableLen)
	{
		_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
		_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
		_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
		_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
		_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
		_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

		_headerTablePos++;
	}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

	/// Get the macroblock (slice data) encodings off the bit stream.
	runOutOfBits = ReadSliceDataLayer(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// Get the slice trailing bits off the bit stream. 
	runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// INTRA frames require the reference images to be zeroed.
	if (_pictureCodingType == H264V2_INTRA)
	{
		Restart();	///< Reset the loop and ref img.

			/// The decoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of macroblocks.
		if (!_pIntraImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end if INTRA...
	else
	{
		/// INTER picture decode.
		/// The decoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end else INTER...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	/// Convert to the output image depending on the output dimension settings. Set
	  /// up in the Open() method for the correctly selected converter.
	if (_outColour == H264V2_YUV420P16)      /// The natural colour space of the decoder with type = short.
		memcpy((void *)pDst, (const void *)_pLum, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_outColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			((unsigned char *)pDst)[i] = (unsigned char)_pLum[i];
	}//end if H264V2_YUV420P8...
	else
		_pOutColourConverter->Convert(_pRLum, _pRChrU, _pRChrV, pDst);

	return(1);

	/// Clean up memory objects.
H264V2_D_CLEAN_MEM:
	if (_pHeaderUnsignedVlcDec != NULL)
	{
		delete _pHeaderUnsignedVlcDec;
		_pHeaderUnsignedVlcDec = NULL;
	}//end if _pHeaderUnsignedVlcDec...
	if (_pHeaderSignedVlcDec != NULL)
	{
		delete _pHeaderSignedVlcDec;
		_pHeaderSignedVlcDec = NULL;
	}//end if _pHeaderSignedVlcDec...
	if (_pBitStreamReader != NULL)
	{
		delete _pBitStreamReader;
		_pBitStreamReader = NULL;
	}//end if _pBitStreamReader...

	return(ret);
}//end Decode.

int H264v2Codec::Close(void)
{
#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos > 0)
		_headerTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC10/CodecAnalyser/LoyisoGola_my_enc_qp48_16P.csv", ",", 1);

	_headerTablePos = 0;
#endif // H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	if (_mbRDTablePos > 1)
		_mbRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/QPvRD_Foreman.csv", ",", 1);

	_mbRDTablePos = 1;
#endif
#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos > 0)
		_timingTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/EncodeTimes.csv", ",", 1);

	_timingTablePos = 0;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
	/// Collect frame RD values.
	_frmRDTableLen = _pRateCntlPFrames->GetFameBufferLength();
	_frmRDTable.Create(4, _frmRDTableLen);  /// frame, mb Dmax, rate, MAD.

	_frmRDTable.SetHeading(0, "Frame");
	_frmRDTable.SetDataType(0, MeasurementTable::INT);
	_frmRDTable.SetHeading(1, "Dmax");
	_frmRDTable.SetDataType(1, MeasurementTable::INT);
	_frmRDTable.SetHeading(2, "Rate");
	_frmRDTable.SetDataType(2, MeasurementTable::DOUBLE);
	_frmRDTable.SetHeading(3, "MAD");
	_frmRDTable.SetDataType(3, MeasurementTable::DOUBLE);

	_frmRDTablePos = 0;

	if (_pRateCntlPFrames->ValidData())
	{
		int frmNum = _frmRDTableLen - 1; ///< Frame numbering is in reverse order.
		for (_frmRDTablePos = 0; _frmRDTablePos < _frmRDTableLen; _frmRDTablePos++, frmNum--)
		{
			_frmRDTable.WriteItem(0, _frmRDTablePos, _frmRDTablePos); ///< Frame counter.
			_frmRDTable.WriteItem(1, _frmRDTablePos, (int)(0.5 + (_pRateCntlPFrames->GetDmaxSamples())[frmNum]));
			_frmRDTable.WriteItem(2, _frmRDTablePos, (_pRateCntlPFrames->GetRateSamples())[frmNum]); ///< In bits/pixel
			_frmRDTable.WriteItem(3, _frmRDTablePos, (_pRateCntlPFrames->GetMDSamples())[frmNum]);
		}//end for _frmRDTablePos...

		_frmRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DmaxVsR_Foreman.csv", ",", 1);
		_frmRDTablePos = 0;
	}//end if ValidData...

#endif

	/// Free the image memory and associated overlays.
	if (_Lum != NULL)
		delete _Lum;
	_Lum = NULL;
	if (_Cb != NULL)
		delete _Cb;
	_Cb = NULL;
	if (_Cr != NULL)
		delete _Cr;
	_Cr = NULL;

	if (_RefLum != NULL)
		delete _RefLum;
	_RefLum = NULL;
	if (_RefCb != NULL)
		delete _RefCb;
	_RefCb = NULL;
	if (_RefCr != NULL)
		delete _RefCr;
	_RefCr = NULL;

	if (_pLum != NULL)
		delete[] _pLum;
	_pLum = NULL;
	_pChrU = NULL;
	_pChrV = NULL;
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;

	if (_16x16 != NULL)
		delete _16x16;
	_16x16 = NULL;
	if (_p16x16 != NULL)
		delete[] _p16x16;
	_p16x16 = NULL;
	if (_8x8_0 != NULL)
		delete _8x8_0;
	_8x8_0 = NULL;
	if (_p8x8_0 != NULL)
		delete[] _p8x8_0;
	_p8x8_0 = NULL;
	if (_8x8_1 != NULL)
		delete _8x8_1;
	_8x8_1 = NULL;
	if (_p8x8_1 != NULL)
		delete[] _p8x8_1;
	_p8x8_1 = NULL;

	if (_mbImg != NULL)
		delete _mbImg;
	_mbImg = NULL;

	/// Colour converters.
	if (_pInColourConverter != NULL)
		delete _pInColourConverter;
	_pInColourConverter = NULL;

	if (_pOutColourConverter != NULL)
		delete _pOutColourConverter;
	_pOutColourConverter = NULL;

	/// IT transform filters.
	if (_pF4x4TLum != NULL)
		delete _pF4x4TLum;
	_pF4x4TLum = NULL;
	if (_pF4x4TChr != NULL)
		delete _pF4x4TChr;
	_pF4x4TChr = NULL;
	if (_pFDC4x4T != NULL)
		delete _pFDC4x4T;
	_pFDC4x4T = NULL;
	if (_pFDC2x2T != NULL)
		delete _pFDC2x2T;
	_pFDC2x2T = NULL;
	if (_pI4x4TLum != NULL)
		delete _pI4x4TLum;
	_pI4x4TLum = NULL;
	if (_pI4x4TChr != NULL)
		delete _pI4x4TChr;
	_pI4x4TChr = NULL;
	if (_pIDC4x4T != NULL)
		delete _pIDC4x4T;
	_pIDC4x4T = NULL;
	if (_pIDC2x2T != NULL)
		delete _pIDC2x2T;
	_pIDC2x2T = NULL;

	/// Vlc encoders and decoders.
	if (_pPrefixVlcEnc != NULL)
		delete _pPrefixVlcEnc;
	_pPrefixVlcEnc = NULL;
	if (_pPrefixVlcDec != NULL)
		delete _pPrefixVlcDec;
	_pPrefixVlcDec = NULL;

	if (_pCoeffTokenVlcEnc != NULL)
		delete _pCoeffTokenVlcEnc;
	_pCoeffTokenVlcEnc = NULL;
	if (_pCoeffTokenVlcDec != NULL)
		delete _pCoeffTokenVlcDec;
	_pCoeffTokenVlcDec = NULL;

	if (_pTotalZeros4x4VlcEnc != NULL)
		delete _pTotalZeros4x4VlcEnc;
	_pTotalZeros4x4VlcEnc = NULL;
	if (_pTotalZeros4x4VlcDec != NULL)
		delete _pTotalZeros4x4VlcDec;
	_pTotalZeros4x4VlcDec = NULL;

	if (_pTotalZeros2x2VlcEnc != NULL)
		delete _pTotalZeros2x2VlcEnc;
	_pTotalZeros2x2VlcEnc = NULL;
	if (_pTotalZeros2x2VlcDec != NULL)
		delete _pTotalZeros2x2VlcDec;
	_pTotalZeros2x2VlcDec = NULL;

	if (_pRunBeforeVlcEnc != NULL)
		delete _pRunBeforeVlcEnc;
	_pRunBeforeVlcEnc = NULL;
	if (_pRunBeforeVlcDec != NULL)
		delete _pRunBeforeVlcDec;
	_pRunBeforeVlcDec = NULL;

	if (_pBlkPattVlcEnc != NULL)
		delete _pBlkPattVlcEnc;
	_pBlkPattVlcEnc = NULL;
	if (_pBlkPattVlcDec != NULL)
		delete _pBlkPattVlcDec;
	_pBlkPattVlcDec = NULL;

	if (_pDeltaQPVlcEnc != NULL)
		delete _pDeltaQPVlcEnc;
	_pDeltaQPVlcEnc = NULL;
	if (_pDeltaQPVlcDec != NULL)
		delete _pDeltaQPVlcDec;
	_pDeltaQPVlcDec = NULL;

	if (_pMbTypeVlcEnc != NULL)
		delete _pMbTypeVlcEnc;
	_pMbTypeVlcEnc = NULL;
	if (_pMbTypeVlcDec != NULL)
		delete _pMbTypeVlcDec;
	_pMbTypeVlcDec = NULL;

	/// Vlc codecs that were used as references and not instantiated.
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// The CAVLC codecs.
	if (_pCAVLC4x4 != NULL)
		delete _pCAVLC4x4;
	_pCAVLC4x4 = NULL;
	if (_pCAVLC2x2 != NULL)
		delete _pCAVLC2x2;
	_pCAVLC2x2 = NULL;

	/// Macroblock data objects.
	if (_pMb != NULL)
		delete[] _pMb;
	_pMb = NULL;
	if (_Mb != NULL)
		delete[] _Mb;
	_Mb = NULL;

	if (_autoIFrameIncluded != NULL)
		delete[] _autoIFrameIncluded;
	_autoIFrameIncluded = NULL;

	/// Stream access.
	if (_pBitStreamWriter != NULL)
		delete _pBitStreamWriter;
	_pBitStreamWriter = NULL;

	if (_pBitStreamReader != NULL)
		delete _pBitStreamReader;
	_pBitStreamReader = NULL;

	/// Motion estimator and compensators.
	if (_pMotionEstimator != NULL)
		delete _pMotionEstimator;
	_pMotionEstimator = NULL;

	/// Motion compensation vectors.
	if (_pMotionVectors != NULL)
		delete _pMotionVectors;
	_pMotionVectors = NULL;

	if (_pMotionCompensator != NULL)
		delete _pMotionCompensator;
	_pMotionCompensator = NULL;

	if (_pMotionPredictor != NULL)
		delete _pMotionPredictor;
	_pMotionPredictor = NULL;

	/// Image plane encoders/decoders.
	if (_pIntraImgPlaneEncoder != NULL)
		delete _pIntraImgPlaneEncoder;
	_pIntraImgPlaneEncoder = NULL;

	if (_pInterImgPlaneEncoder != NULL)
		delete _pInterImgPlaneEncoder;
	_pInterImgPlaneEncoder = NULL;

	if (_pIntraImgPlaneDecoder != NULL)
		delete _pIntraImgPlaneDecoder;
	_pIntraImgPlaneDecoder = NULL;

	if (_pInterImgPlaneDecoder != NULL)
		delete _pInterImgPlaneDecoder;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	if (_pRateCntlPFrames != NULL)
	{
		_pRateCntlPFrames->Dump(H264V2_RATE_CNTL_PFRAMES);
		//    _pRateCntlPFrames->Dump();
		delete _pRateCntlPFrames;
		_pRateCntlPFrames = NULL;
	}//end if _pRateCntlPFrames...
	if (_pRateCntlIFrames != NULL)
	{
		_pRateCntlIFrames->Dump(H264V2_RATE_CNTL_IFRAMES);
		delete _pRateCntlIFrames;
		_pRateCntlIFrames = NULL;
	}//end if _pRateCntlIFrames...

  /// Region of Interest encoding.
  if (_roiMultiplier != NULL)
    delete[] _roiMultiplier;
  _roiMultiplier = NULL;

	_codecIsOpen = 0;
	return(1);
}//end Close.

void H264v2Codec::Restart(void)
{
	_pictureCodingType = H264V2_INTRA;
	_frameNum = 0;				///< Reset the frame counter.
  /// _idrFrameNum does not require reseting.

  /// Zero the reference image. Note that the colour components are 
	/// held in contiguous mem.
	int imgSize = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
	memset(_pRLum, 0, imgSize * sizeof(short));

}//end Restart.

/*
-----------------------------------------------------------------------
  Private Implementation.
-----------------------------------------------------------------------
*/
/** Code non-picture nal types.
This method operates independently and therefore all the coding objects must be
instantiated and destroyed before and after the coding process. This is typically an
out-of-band process and therefore speed is not critical. The codec must NOT be open
for calls to this method i.e. _codecIsOpen = 0.
@param pCmp						: The stream memory to write to.
@param frameBitLimit	: The max number of bits to use.
@return								: 1 = success, 0 = failure.
*/
int H264v2Codec::CodeNonPicNALTypes(void* pCmp, int frameBitLimit)
{
	int allowedBits, bitsUsed;

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit;
	int ret = 1;	///< Return value default to success.
	_bitStreamSize = 0;

	/// This method uses the class members and therefore Open() must not be called before
	/// coding non-pic nal-types.
	if (_codecIsOpen)
	{
		_errorStr = "[H264V2::CodeNonPicNALTypes] Codec must not be open for non-picture nal types";
		return(0);
	}//end if _codecIsOpen...

	  /// Check which types are supported with this implementation.
	if ((_pictureCodingType != H264V2_SEQ_PARAM) && (_pictureCodingType != H264V2_PIC_PARAM))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Non-Nal picture type not supported";
		return(0);
	}//end if !H264V2_SEQ_PARAM...

	///----------------------------------------------------------------------------------------------
	/// Instantiate the mem objects required for the encoding.

	/// A stream writer.
	_pBitStreamWriter = new BitStreamWriterMSB();
	if (_pBitStreamWriter == NULL)
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate bit stream writer object";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if !_pBitStreamWriter...
	/// Set the stream writer to the compressed input parameter reference.
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pHeaderSignedVlcEnc = new ExpGolombSignedVlcEncoder();
	if ((_pHeaderUnsignedVlcEnc == NULL) || (_pHeaderSignedVlcEnc == NULL))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate vlc encoder objects";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if _pHeaderUnsignedVlcEnc...

	///----------------------------------------------------------------------------------------------
	/// Parameter set coding. The _currSeqParam and _currPicParam members determine the param sets
	/// to encode. From here the picture coding type is only H264V2_SEQ_PARAM or H264V2_PIC_PARAM.

	_nal._ref_idc = 3;

	if (_pictureCodingType == H264V2_SEQ_PARAM)
	{
		_nal._unit_type = NalHeaderH264::SeqParamSet;
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set sequence parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetSeqParamSet...
	}//end if H264V2_SEQ_PARAM...
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
	{
		_nal._unit_type = NalHeaderH264::PicParamSet;
		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set picture parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetPicParamSet...
	}//end else...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::CodeNonPicNALTypes] Cannot write start code to stream";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write the parameter set to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (_pictureCodingType == H264V2_SEQ_PARAM)
		runOutOfBits = WriteSeqParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currSeqParam);
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
		runOutOfBits = WritePicParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currPicParam);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write trailing bits to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	///----------------------------------------------------------------------------------------------
	/// Clean up memory objects.
H264V2_CNPNT_CLEAN_MEM:
	if (_pHeaderUnsignedVlcEnc != NULL)
	{
		delete _pHeaderUnsignedVlcEnc;
		_pHeaderUnsignedVlcEnc = NULL;
	}//end if _pHeaderUnsignedVlcEnc...
	if (_pHeaderSignedVlcEnc != NULL)
	{
		delete _pHeaderSignedVlcEnc;
		_pHeaderSignedVlcEnc = NULL;
	}//end if _pHeaderSignedVlcEnc...
	if (_pBitStreamWriter != NULL)
	{
		delete _pBitStreamWriter;
		_pBitStreamWriter = NULL;
	}//end if _pBitStreamWriter...

	return(ret);
}//end CodeNonPicNALTypes.

/** Set the Sequence parameter set.
Set one of the seq param sets defined by the index parameter where the
values are determined by interpreting the codec parameters.
@param index	:	Seq parameter set to modify [0..31].
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetSeqParamSet(int index)
{
	if (index > 31)
		return(0);

	_seqParam[index]._seq_parameter_set_id = index;					///< The index for this definition of sequence params [0..31].
	_seqParam[index]._profile_idc = 66;							///< Baseline profile = 66.
	_seqParam[index]._constraint_set0_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set1_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set2_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set3_flag = 0;							///< = 0.
	_seqParam[index]._level_idc = 20;							///< = 20 (Level num = 2, calculated as 10 x level num).
	_seqParam[index]._chroma_format_idc = 1;							///< Range = [0..3]. When not present = 1 (4:2:0).
	_seqParam[index]._residual_colour_transform_flag = 0;							///< = 0.
	_seqParam[index]._bit_depth_luma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/lum component).
	_seqParam[index]._bit_depth_chroma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/chr component).
	_seqParam[index]._qpprime_y_zero_transform_bypass_flag = 0;							///< If QP = 0, this flag indicates bypassing the transform process. When not present = 0.
	_seqParam[index]._seq_scaling_matrix_present_flag = 0;							///< = 0. No scaling matrices for baseline profile. Indicates existence of _seq_scaling_list_present_flag flags.
	/// Not initialised _seq_scaling_list_present_flag[8]			///< if _seq_scaling_matrix_present_flag, these indicate lists not present/present (0/1).
	_seqParam[index]._log2_max_frame_num_minus4 = _seqParamSetLog2MaxFrameNumMinus4;	///< Range = [0..12]. MaxFrameNum = 2^(_log2_max_frame_num_minus4 + 4) for slice _frame_num derivations.
	_seqParam[index]._pic_order_cnt_type = 2;							///< Range = [0..2]. 2 = 1-to-1 mapping. (Picture order count = frame num).
	_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = 0;							///< For B-Slice decoding.  There are no B-Slices in the baseline profile. 
	_seqParam[index]._delta_pic_order_always_zero_flag = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_non_ref_pic = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_top_to_bottom_field = 0;							///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = 0;							///< For B-Slice decoding.
	/// Not initialised _offset_for_ref_frame[256];						///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames = 1;							///< Max num of short-term and long-term ref frames.
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = 0;							///< Indicates allowed values of slice _frame_num.
	_seqParam[index]._frame_mbs_only_flag = 1;							///< = 1 (baseline profile). fields/frames = 0/1.
	_seqParam[index]._mb_adaptive_frame_field_flag = 0;							///< Indicates switching between frame and field macroblocks. When not present = 0.
	_seqParam[index]._direct_8x8_inference_flag = 0;							///< Methods for B-Slice motion vector decoding. There are no B-Slices in the baseline profile.
	_seqParam[index]._frame_cropping_flag = 0;							///< Indicates that the cropping params below follow in the stream.
	_seqParam[index]._frame_crop_left_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_right_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_top_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_bottom_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._vui_parameters_present_flag = 0;							///< vui parameters follow.

	if ((_width < 16) || (_height < 16))
		return(0);

	_seqParam[index]._pic_width_in_mbs_minus1 = (_width / 16) - 1;	///< Width of decoded pic in units of macroblocks. Derive lum and chr pic width from this variable.
	_seqParam[index]._pic_height_in_map_units_minus1 = (_height / 16) - 1;	///< Map units are 2 macroblocks for fields and 1 for frames. Derive lum and chr pic height from this variable.

	return(1);
}//end SetSeqParamSet.

/** Write the sequence parameter set to a bit stream.
The seq param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Sequence parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;

	/// Only baseline profile is supported: _profile_idc = 66.
//	if(_seqParam[index]._profile_idc != 66)
//	{
//		_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 0;
//		return(3);
//	}//end if _profile_idc not baseline...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (allowedBits < 24)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
	{
		bsw->Write(8, _seqParam[index]._profile_idc);						///< u(8)
		bsw->Write(_seqParam[index]._constraint_set0_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set1_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set2_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set3_flag);			///< u(1)
		bsw->Write(4, 0);																				///< u(4), reserved_zero_4bits.
		bsw->Write(8, _seqParam[index]._level_idc);							///< u(8)
	}//end if bsw...
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._seq_parameter_set_id);  ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._chroma_format_idc);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _residual_colour_transform_flag
		if (_seqParam[index]._chroma_format_idc == 3)
		{
			if (bsw)
				bsw->Write(_seqParam[index]._residual_colour_transform_flag); ///< u(1)
			bitsUsedSoFar++;
		}///end if _chroma_format_idc...

		/// _bit_depth_luma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_luma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _bit_depth_chroma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_chroma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// Two flags
		if (bsw)
		{
			bsw->Write(_seqParam[index]._qpprime_y_zero_transform_bypass_flag); ///< u(1)
			bsw->Write(_seqParam[index]._seq_scaling_matrix_present_flag);      ///< u(1)
		}//end if bsw...
		bitsUsedSoFar += 2;

		/// Scaling matricies
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				/// _seq_scaling_list_present_flag[8]
				if (bsw)
					bsw->Write(_seqParam[index]._seq_scaling_list_present_flag[i]); ///< u(1)
				bitsUsedSoFar++;

				bitCount = 0;
				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
				bitsUsedSoFar += bitCount;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_frame_num_minus4); ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_order_cnt_type
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_order_cnt_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._delta_pic_order_always_zero_flag);
		bitsUsedSoFar++;

		/// _offset_for_non_ref_pic
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_non_ref_pic);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _offset_for_top_to_bottom_field
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_top_to_bottom_field);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_ref_frame[i]);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_WSPS_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _gaps_in_frame_num_value_allowed_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._gaps_in_frame_num_value_allowed_flag);
	bitsUsedSoFar++;

	/// _pic_width_in_mbs_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_width_in_mbs_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_height_in_map_units_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_height_in_map_units_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _frame_mbs_only_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_mbs_only_flag);
	bitsUsedSoFar++;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._mb_adaptive_frame_field_flag);
		bitsUsedSoFar++;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._direct_8x8_inference_flag);
	bitsUsedSoFar++;

	/// _frame_cropping_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_cropping_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_left_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_right_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_right_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_top_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_top_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_bottom_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_bottom_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._vui_parameters_present_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: Implement VUI encoding.
	}//end if _vui_parameters_present_flag...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSeqParamSet.

/// This method has not been tested and at first glance does not look correct
int H264v2Codec::WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, bitCount;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			nextScale = scalingList[j];

			/// deltaScale
			int deltaScale = nextScale - lastScale;
			bitCount = _pHeaderSignedVlcEnc->Encode(deltaScale);  ///< se(v)
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				return(bitsUsed);
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsed += bitCount;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end WriteSeqParamScalingList.

/** Read the sequence parameter set from the bit stream.
This impementation reads sequence parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to seq param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits, i;
	int li;
	int pi;
	int set0_flag;
	int set1_flag;
	int set2_flag;
	int set3_flag;
	int index;

	SeqParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "H264V2:[H264Codec::ReadSeqParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (remainingBits < 24)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// Temporarily read up to the _seq_parameter_set_id that defines the index into the
	/// _seqParam[] array.

	pi = bsr->Read(8);																		///< u(8):_profile_idc
	/// Only baseline profile is supported: _profile_idc = 66.
//	if(pi != 66)
//	{
//		_errorStr = "[H264Codec::ReadSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 8;
//		return(2);
//	}//end if pi not baseline...
	set0_flag = bsr->Read();															///< u(1):_constraint_set0_flag
	set1_flag = bsr->Read();															///< u(1):_constraint_set1_flag
	set2_flag = bsr->Read();															///< u(1):_constraint_set2_flag
	set3_flag = bsr->Read();															///< u(1):_constraint_set3_flag
	bsr->Read(4);																							///< u(4), reserved_zero_4bits ignored.
	li = bsr->Read(8);																		///< u(8):_level_idc
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the array index.
	if ((index < 0) || (index > 31))
	{
		_errorStr = "[H264Codec::ReadSeqParamSet] Sequence parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_seqParam[index]));

	/// The array index is now known and within range so the structure can be checked and loaded from the
	/// temporary variables.
	_seqParam[index]._profile_idc = pi;
	_seqParam[index]._constraint_set0_flag = set0_flag;
	_seqParam[index]._constraint_set1_flag = set1_flag;
	_seqParam[index]._constraint_set2_flag = set2_flag;
	_seqParam[index]._constraint_set3_flag = set3_flag;
	_seqParam[index]._level_idc = li;
	_seqParam[index]._seq_parameter_set_id = index;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		_seqParam[index]._chroma_format_idc = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		if (_seqParam[index]._chroma_format_idc == 3)
		{
			_seqParam[index]._residual_colour_transform_flag = bsr->Read(); ///< u(1)
			bitsUsedSoFar++;
		}//end if _chroma_format_idc...

		  /// _bit_depth_luma_minus8
		_seqParam[index]._bit_depth_luma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _bit_depth_chroma_minus8
		_seqParam[index]._bit_depth_chroma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Two flags.
		_seqParam[index]._qpprime_y_zero_transform_bypass_flag = bsr->Read(); ///< u(1)
		_seqParam[index]._seq_scaling_matrix_present_flag = bsr->Read(); ///< u(1)
		bitsUsedSoFar += 2;

		/// _seq_scaling_list_present_flag[]
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				_seqParam[index]._seq_scaling_list_present_flag[i] = bsr->Read(); ///< u(1)
				bitsUsedSoFar++;

				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSPS_RUNOUTOFBITS_READ;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	_seqParam[index]._log2_max_frame_num_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_order_cnt_type
	_seqParam[index]._pic_order_cnt_type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		_seqParam[index]._delta_pic_order_always_zero_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_non_ref_pic
		_seqParam[index]._offset_for_non_ref_pic = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_top_to_bottom_field
		_seqParam[index]._offset_for_top_to_bottom_field = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			_seqParam[index]._offset_for_ref_frame[i] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSPS_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSPS_RUNOUTOFBITS_READ;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	_seqParam[index]._num_ref_frames = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _gaps_in_frame_num_value_allowed_flag
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_width_in_mbs_minus1
	_seqParam[index]._pic_width_in_mbs_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_height_in_map_units_minus1
	_seqParam[index]._pic_height_in_map_units_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_mbs_only_flag
	_seqParam[index]._frame_mbs_only_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		_seqParam[index]._mb_adaptive_frame_field_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	_seqParam[index]._direct_8x8_inference_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_cropping_flag
	_seqParam[index]._frame_cropping_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		_seqParam[index]._frame_crop_left_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_right_offset
		_seqParam[index]._frame_crop_right_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_top_offset
		_seqParam[index]._frame_crop_top_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_bottom_offset
		_seqParam[index]._frame_crop_bottom_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	_seqParam[index]._vui_parameters_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: ReadSeqParamVuiParams() does not work properly and must be debugged.
			//numBits = ReadSeqParamVuiParams(bsr);
			//bitsUsedSoFar += numBits;
			//if( bitsUsedSoFar > remainingBits )
			//	goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Dummy read all the bits except the last one to leave the bsr pointer on the last bit.
		int pos = bsr->GetStreamBitPos();
		numBits = remainingBits - bitsUsedSoFar - 1;
		bsr->Read(numBits);
		/// Search backwards until the trailing stop bit is found.
		pos = bsr->GetStreamBitPos();
		while (bsr->Peek(pos, 1) != 1)
		{
			pos++;
			numBits--;
		}//end while Peek...
		/// Set the bsr to point at the stop bit.
		bsr->Seek(pos);
		bitsUsedSoFar += numBits;

	}//end if _vui_parameters_present_flag...

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_seqParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSeqParamSet.

/// This method has not been tested.
int H264v2Codec::ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, numBits;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			/// deltaScale 
			int deltaScale = _pHeaderSignedVlcDec->Decode(bsr); ///< se(v)
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				return(bitsUsed);
			bitsUsed += numBits;

			nextScale = (lastScale + deltaScale + 256) % 256;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		if (nextScale == 0)
			scalingList[j] = lastScale;
		else
			scalingList[j] = nextScale;
		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end ReadSeqParamScalingList.

/** Read the vui parameters from a sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	/// Aspect ratio info
	unsigned int aspect_ratio_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (aspect_ratio_info_present_flag)
	{
		unsigned int aspect_ratio_idc = bsr->Read(8); ///< u(8)
		bitsUsed += 8;
		if (aspect_ratio_idc == 255) ///< Extended_SAR
		{
			unsigned int sar_width = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
			unsigned int sar_height = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
		}//end if aspect_ratio_idc...
	}//end if aspect_ratio_info_present_flag...

	/// Overscan info
	unsigned int overscan_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (overscan_info_present_flag)
	{
		unsigned int overscan_appropriate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if overscan_info_present_flag...

	/// Video signal type info
	unsigned int video_signal_type_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (video_signal_type_present_flag)
	{
		unsigned int video_format = bsr->Read(3); ///< u(3)
		bitsUsed += 3;
		unsigned int video_full_range_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int colour_description_present_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		if (colour_description_present_flag)
		{
			unsigned int colour_primaries = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int transfer_characteristics = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int matrix_coefficients = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
		}//end if colour_description_present_flag...
	}//end if video_signal_type_present_flag...

	/// Chroma location info
	unsigned int chroma_loc_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (chroma_loc_info_present_flag)
	{
		unsigned int chroma_sample_loc_type_top_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int chroma_sample_loc_type_bottom_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if chroma_loc_info_present_flag...

	/// Timing info
	unsigned int timing_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (timing_info_present_flag)
	{
		unsigned int num_units_in_tick = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int time_scale = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int fixed_frame_rate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if timing_info_present_flag...

	/// HRD parameter info
	unsigned int nal_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (nal_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if nal_hrd_parameters_present_flag...
	unsigned int vcl_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (vcl_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if vcl_hrd_parameters_present_flag...
	if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
	{
		unsigned int low_delay_hrd_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if nal_hrd_parameters_present_flag...

	/// Picture structure info
	unsigned int pic_struct_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;

	/// Bit stream restriction info
	unsigned int bitstream_restriction_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (bitstream_restriction_flag)
	{
		unsigned int motion_vectors_over_pic_boundaries_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int max_bytes_per_pic_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_bits_per_mb_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_horizontal = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_vertical = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int num_reorder_frames = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_dec_frame_buffering = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if bitstream_restriction_flag...

	return(bitsUsed);
}//end ReadSeqParamVuiParams.

/** Read the hrd parameters from a vui sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiHrdParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	unsigned int cpb_cnt_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
	bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();

	unsigned int bit_rate_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	unsigned int cpb_size_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	for (unsigned int schedSelIdx = 0; schedSelIdx <= cpb_cnt_minus1; schedSelIdx++)
	{
		/// This is a dummy method but the actual method will fill bit_rate_value_minus1[schedSelIdx] array.
		unsigned int bit_rate_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cpb_size_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cbr_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end for schedSelIdx...

	unsigned int initial_cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int dpb_output_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int time_offset_length = bsr->Read(5); ///< u(5)
	bitsUsed += 5;

	return(bitsUsed);
}//endReadSeqParamVuiHrdParams. 

/** Set the Picture parameter set.
Set one of the pic param sets defined by the index parameters where the
values are determined by interpreting the codec parameters.
@param index	:	Pic parameter set to modify [0..255].
@param seqRef	: Seq param set to reference.
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetPicParamSet(int index, int seqRef)
{
	if ((index > 255) || (seqRef > 31))
		return(0);

	_picParam[index]._pic_parameter_set_id = index;	///< The index for this definition of picture params [0..255].
	_picParam[index]._seq_parameter_set_id = seqRef;	///< This pic param set refers to this seq param set. Range = [0..31].
	_picParam[index]._entropy_coding_mode_flag = 0;			///< Baseline profile = 0. CAVLC/CABAC = 0/1.
	_picParam[index]._pic_order_present_flag = 0;			///< Pic order count syntax elements are present in the slice header.
	_picParam[index]._num_slice_groups_minus1 = 0;			///< = 0 (baseline profile). Num of slice groups for a pic.
	_picParam[index]._slice_group_map_type = 0;			///< Defines map units to slice groups. Range = [0..6].
	/// Not initialised: _run_length_minus1[7];									///< Slice group mapping.
	/// Not initialised: _top_left[7];													///< Slice group mapping.
	/// Not initialised: _bottom_right[7];											///< Slice group mapping.
	_picParam[index]._slice_group_change_direction_flag = 0;			///< Slice group mapping.
	_picParam[index]._slice_group_change_rate_minus1 = 0;			///< Slice group mapping.
	/// Not initialised: _slice_group_id[7];										///< Slice group mapping.
	_picParam[index]._num_ref_idx_l0_active_minus1 = 0;			///< Max ref index for ref pic list0.
	_picParam[index]._num_ref_idx_l1_active_minus1 = 0;			///< Max ref index for ref pic list1. (For B-Slices)
	_picParam[index]._weighted_pred_flag = 0;			///< Indicates weighted prediction applied to P-Slices.
	_picParam[index]._weighted_bipred_idc = 0;			///< Weighted prediction type applied to B-Slices.
	_picParam[index]._pic_init_qp_minus26 = 0;			///< Initial value of lum SliceQP - 26 for each slice. The slice_qp_delta modifies this value. Rng = [-26..25].
	_picParam[index]._pic_init_qs_minus26 = 0;			///< For SP and SI slices.
	_picParam[index]._chroma_qp_index_offset = 0;			///< Offset added to lum QP (and QS) for Cb chr QP values. Rng = [-12..12].
	_picParam[index]._second_chroma_qp_index_offset = 0;			///< For Cr chr QP. When not present = _chroma_qp_index_offset above.
	_picParam[index]._deblocking_filter_control_present_flag = 0;			///< Indicates presence of elements in slice header to change the characteristics of the deblocking filter.
	_picParam[index]._constrained_intra_pred_flag = 1;			///< = 1. Indicates that intra macroblock prediction can only be done from other intra macroblocks. 
	_picParam[index]._redundant_pic_cnt_present_flag = 0;			///< Indicates that redundant pic count elements are in the slice header.
	_picParam[index]._transform_8x8_mode_flag = 0;			///< = 0. Indicates 8x8 transform is used. When not present = 0.
	_picParam[index]._pic_scaling_matrix_present_flag = 0;			///< = 0. Indicates params are present to modify the scaling lists specified in the seq param sets.
	/// Not initialised:_pic_scaling_list_present_flag[8];			///< Scaling list syntax structure present for scaling list i = 0..7.

	_picParam[index]._pic_size_in_map_units_minus1 = ((_width / 16)*(_height / 16)) - 1;	///< Num of map units (macroblocks for frames) in the pic. Macroblock width * height.

	return(1);
}//end SetPicParamSet.

/** Write the picture parameter set to a bit stream.
The pic param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Picture parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// _pic_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._pic_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._seq_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _entropy_coding_mode_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._entropy_coding_mode_flag);
	bitsUsedSoFar++;

	/// _pic_order_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._pic_order_present_flag);
	bitsUsedSoFar++;

	/// _num_slice_groups_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_slice_groups_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_WPPS_MODEERROR_WRITE;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l0_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _num_ref_idx_l1_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l1_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _weighted_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._weighted_pred_flag);
	bitsUsedSoFar++;

	/// _weighted_bipred_idc
	if ((bitsUsedSoFar + 2) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(2, _picParam[index]._weighted_bipred_idc);
	bitsUsedSoFar += 2;

	/// _pic_init_qp_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qp_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_init_qs_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qs_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _chroma_qp_index_offset
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._chroma_qp_index_offset);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _deblocking_filter_control_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._deblocking_filter_control_present_flag);
	bitsUsedSoFar++;

	/// _constrained_intra_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._constrained_intra_pred_flag);
	bitsUsedSoFar++;

	/// _redundant_pic_cnt_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._redundant_pic_cnt_present_flag);
	bitsUsedSoFar++;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WPPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WPPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WPPS_MODEERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WritePicParamSet.

/** Read the picture parameter set from the bit stream.
This impementation reads picture parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to pic param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits;
	PicParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "[H264Codec::ReadPicParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// _pic_parameter_set_id
	int index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the pic param array index.
	if ((index < 0) || (index > 255))
	{
		_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_picParam[index]));

	/// The decoded index identifies the param set to use.
	_picParam[index]._pic_parameter_set_id = index;

	/// _seq_parameter_set_id
	_picParam[index]._seq_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// Range check on the seq param array index. This does not test if the data in the _seqParam[]
	/// array for this id is valid.
	if ((_picParam[index]._seq_parameter_set_id < 0) || (_picParam[index]._seq_parameter_set_id > 31))
	{
		_errorStr = "H264V2:[H264Codec::ReadPicParamSet] Sequence parameter set index of picture parameter set is out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

	/// _entropy_coding_mode_flag
	_picParam[index]._entropy_coding_mode_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_order_present_flag
	_picParam[index]._pic_order_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_slice_groups_minus1
	_picParam[index]._num_slice_groups_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_RPPS_NOMODE_READ;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	_picParam[index]._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_ref_idx_l1_active_minus1
	_picParam[index]._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_pred_flag
	_picParam[index]._weighted_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_bipred_idc
	_picParam[index]._weighted_bipred_idc = bsr->Read(2);
	bitsUsedSoFar += 2;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qp_minus26
	_picParam[index]._pic_init_qp_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qs_minus26
	_picParam[index]._pic_init_qs_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _chroma_qp_index_offset
	_picParam[index]._chroma_qp_index_offset = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _deblocking_filter_control_present_flag
	_picParam[index]._deblocking_filter_control_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _constrained_intra_pred_flag
	_picParam[index]._constrained_intra_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _redundant_pic_cnt_present_flag
	_picParam[index]._redundant_pic_cnt_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_picParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RPPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RPPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RPPS_NOMODE_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadPicParamSet.

/** Get the codec parameters.
Load the codec params from the picture param set indexed by
the input param. The sequence param set is implied in the referenced
pic param set. The pic/seq param set must be previously defined
prior to calling this method.
@param picParamSet	:	Pic parameter set to get from [0..255].
@return							: Success = 1, failure = 0.
*/
int H264v2Codec::GetCodecParams(int picParamSet)
{
	///----------- Some parameter set range checking ------------------------------
	if ((picParamSet < 0) || (picParamSet > 255))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set out of range";
		return(0);
	}//end if picParamSet...
	if (_picParam[picParamSet]._pic_parameter_set_id != picParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set mismatch";
		return(0);
	}//end if _pic_parameter_set_id...
	int seqParamSet = _picParam[picParamSet]._seq_parameter_set_id;
	if ((seqParamSet < 0) || (seqParamSet > 31))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set out of range";
		return(0);
	}//end if seqParamSet...
	if (_seqParam[seqParamSet]._seq_parameter_set_id != seqParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set mismatch";
		return(0);
	}//end if _seq_parameter_set_id...
	/// Modify the codec seq param set to that associated with this pic param set.
	_currSeqParam = seqParamSet;

	///----------- Extract params of interest for codec -----------------------
	/// Get width and height in pels.
	_width = (_seqParam[seqParamSet]._pic_width_in_mbs_minus1 + 1) * 16;
	_height = (_seqParam[seqParamSet]._pic_height_in_map_units_minus1 + 1) * 16;
	_seqParamSetLog2MaxFrameNumMinus4 = _seqParam[seqParamSet]._log2_max_frame_num_minus4;

	///----------- Check params for this implementation -----------------------

	/// Sequence parameter implementation.
	if ((_seqParam[seqParamSet]._profile_idc != 66) ||
		(_seqParam[seqParamSet]._constraint_set0_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set1_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set2_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set3_flag != 0) ||
		(_seqParam[seqParamSet]._level_idc != 20) ||
		(_seqParam[seqParamSet]._chroma_format_idc != 1) ||
		(_seqParam[seqParamSet]._bit_depth_luma_minus8 != 0) ||
		(_seqParam[seqParamSet]._bit_depth_chroma_minus8 != 0) ||
		(_seqParam[seqParamSet]._qpprime_y_zero_transform_bypass_flag != 0) ||
		(_seqParam[seqParamSet]._seq_scaling_matrix_present_flag != 0) ||
		(_seqParam[seqParamSet]._pic_order_cnt_type != 2) ||
		(_seqParam[seqParamSet]._num_ref_frames != 1) ||
		(_seqParam[seqParamSet]._gaps_in_frame_num_value_allowed_flag != 0) ||
		(_seqParam[seqParamSet]._frame_mbs_only_flag != 1) ||
		(_seqParam[seqParamSet]._mb_adaptive_frame_field_flag != 0) ||
		(_seqParam[seqParamSet]._direct_8x8_inference_flag != 0) ||
		(_seqParam[seqParamSet]._frame_cropping_flag != 0) ||
		(_seqParam[seqParamSet]._vui_parameters_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameters not implemented";
		return(0);
	}//end if _profile_idc...

	/// Picture parameter implementation.
	if ((_picParam[picParamSet]._entropy_coding_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_order_present_flag != 0) ||
		(_picParam[picParamSet]._num_slice_groups_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l0_active_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l1_active_minus1 != 0) ||
		(_picParam[picParamSet]._weighted_pred_flag != 0) ||
		(_picParam[picParamSet]._weighted_bipred_idc != 0) ||
		(_picParam[picParamSet]._constrained_intra_pred_flag != 1) ||
		(_picParam[picParamSet]._redundant_pic_cnt_present_flag != 0) ||
		(_picParam[picParamSet]._transform_8x8_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_scaling_matrix_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameters not implemented";
		return(0);
	}//end if _profile_idc...

	return(1);
}//end GetCodecParams.

/** Write the NAL header to a bit stream.
The NAL header data must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit overflow
will occur before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (allowedBits >= 8)
	{
		if (bsw)
		{
			bsw->Write(1, 0);												///< Forbidden zero bit f(1).
			bsw->Write(2, (_nal._ref_idc & 3));			///< u(2).		
			bsw->Write(5, (_nal._unit_type & 31));	///< u(5).		
		}//end if bsw != NULL...
	}//end if allowedBits...
	else
	{
		_errorStr = "H264V2:[WriteNALHeader] Bits required exceeds max available for NAL header";
		*bitsUsed = 0;
		return(1);
	}///end else...

	*bitsUsed = 8;
	return(0);
}//end WriteNALHeader.

/** Read the NAL header from the bit stream.
This impementation reads the NAL header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (remainingBits >= 8)
	{
		bsr->Read();													///< Discard forbidden zero bit f(1).
		_nal._ref_idc = 3 & bsr->Read(2);		///< u(2).
		_nal._unit_type = 31 & bsr->Read(5);	///< u(5).
	}//end if remainingBits...
	else
	{
		_errorStr = "H264V2:[ReadNALHeader] Insufficient bits to decode the NAl header";
		*bitsUsed = 0;
		return(1);
	}//end else...

	*bitsUsed = 8;
	return(0);
}//end ReadNALHeader.

/** Write the slice layer header to a bit stream.
The encodings of all the slice data must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. Each write checks if a bit overflow will occur before writing.
The check is sufficiently frequent to warrant an early exit GOTO
statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int	  bitCount;
	int   bitsUsedSoFar = 0;
	char  errInfo[64];
	char  buff[64];

		/// Limited implementation of modes and types for Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_WSLH_MODEERROR_WRITE;

	///-------------------------- Addr of first macroblock -----------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._first_mb_in_slice);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_first_mb_in_slice=");
		sprintf((char *)buff, "%d", _slice._first_mb_in_slice);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._first_mb_in_slice, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Slice Type -------------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._type);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_type=");
		sprintf((char *)buff, "%d", _slice._type);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._type, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Pic Param Set Id --------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._pic_parameter_set_id);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_pic_parameter_set_id=");
		sprintf((char *)buff, "%d", _slice._pic_parameter_set_id);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._pic_parameter_set_id, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Frame Number -----------------------------------------------
	bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	if ((bitsUsedSoFar + bitCount) <= allowedBits)
	{
		if (bsw)
			bsw->Write(bitCount, _slice._frame_num);
	}//end if bitsUsedSoFar...
	else
		goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	bitsUsedSoFar += bitCount;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		if ((bitsUsedSoFar + 2) <= allowedBits)	///< Both flags together.
		{
			if (bsw)
				bsw->Write(_slice._field_pic_flag);
			bitsUsedSoFar++;
			if (_slice._field_pic_flag)
			{
				if (bsw)
					bsw->Write(_slice._bottom_field_flag);
				bitsUsedSoFar++;
			}//end if _field_pic_flag...
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._idr_pic_id);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
				{
					if (bitCount <= 32)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					else
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetExtCode(), _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bsw...
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_idr_pic_id=");
			sprintf((char *)buff, "%d", _slice._idr_pic_id);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._idr_pic_id, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _slice._pic_order_cnt_lsb);
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt_bottom);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt_bottom=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt_bottom);
				strcat(errInfo, buff);
				// strcat(errInfo, itoa(_slice._delta_pic_order_cnt_bottom, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[0]);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_delta_pic_order_cnt[0]=");
			sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[0]);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[0], buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[1]);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt[1]=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[1]);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[1], buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._redundant_pic_cnt);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_redundant_pic_cnt=");
			sprintf((char *)buff, "%d", _slice._redundant_pic_cnt);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._redundant_pic_cnt, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._direct_spatial_mv_pred_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::B_Slice) ||
		(_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._num_ref_idx_active_override_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._num_ref_idx_active_override_flag)
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l0_active_minus1);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_num_ref_idx_l0_active_minus1=");
				sprintf((char *)buff, "%d", _slice._num_ref_idx_l0_active_minus1);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._num_ref_idx_l0_active_minus1, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice))
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l1_active_minus1);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_num_ref_idx_l1_active_minus1=");
					sprintf((char *)buff, "%d", _slice._num_ref_idx_l1_active_minus1);
					strcat(errInfo, buff);
					//strcat(errInfo, itoa(_slice._num_ref_idx_l1_active_minus1, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._ref_pic_list_reordering_flag_l0);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._reordering_of_pic_nums_idc);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_reordering_of_pic_nums_idc=");
					sprintf((char *)buff, "%d", _slice._reordering_of_pic_nums_idc);
					strcat(errInfo, buff);
					// strcat(errInfo, itoa(_slice._reordering_of_pic_nums_idc, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{

					// TODO: Prepare list 0 reordering with _slice._abs_diff_pic_num_minus1.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._abs_diff_pic_num_minus1);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_abs_diff_pic_num_minus1=");
						sprintf((char *)buff, "%d", _slice._abs_diff_pic_num_minus1);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._abs_diff_pic_num_minus1, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{

					// TODO: Prepare list 0 reordering with _slice._long_term_pic_num.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._long_term_pic_num);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_long_term_pic_num=");
						sprintf((char *)buff, "%d", _slice._long_term_pic_num);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._long_term_pic_num, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...

	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			if ((bitsUsedSoFar + 2) <= allowedBits)
			{
				if (bsw)
				{
					bsw->Write(_slice._no_output_of_prior_pics_flag);
					bsw->Write(_slice._long_term_reference_flag);
				}//end if bsw...
				bitsUsedSoFar += 2;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if IDR_Slice...
		else
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._adaptive_ref_pic_marking_mode_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_WSLH_MODEERROR_WRITE;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation ----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._cabac_init_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_cabac_init_idc=");
			sprintf((char *)buff, "%d", _slice._cabac_init_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._cabac_init_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qp_delta);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_qp_delta=");
		sprintf((char *)buff, "%d", _slice._qp_delta);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._qp_delta, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SI_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._sp_for_switch_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if SP_Slice...

		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qs_delta);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_qs_delta=");
			sprintf((char *)buff, "%d", _slice._qs_delta);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._qs_delta, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._disable_deblocking_filter_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_disable_deblocking_filter_idc=");
			sprintf((char *)buff, "%d", _slice._disable_deblocking_filter_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._disable_deblocking_filter_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._alpha_c0_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_alpha_c0_offset_div2=");
				sprintf((char *)buff, "%d", _slice._alpha_c0_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._alpha_c0_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._beta_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_beta_offset_div2=");
				sprintf((char *)buff, "%d", _slice._beta_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._beta_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _disable_deblocking_filter_idc...

	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_WSLH_MODEERROR_WRITE;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSLH_RUNOUTOFBITS_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSLH_VLCERROR_WRITE:
	strcpy(_errorInfo, "[H264v2Codec::WriteSliceLayerHeader] Vlc encoder error: ");
	strcat(_errorInfo, errInfo);
	_errorStr = _errorInfo;
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WSLH_MODEERROR_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceLayerHeader.

/** Read the slice layer header from the bit stream.
This impementation reads slice header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int numBits;

	if (bsr == NULL)
	{
		_errorStr = "[H264V2::ReadSliceLayerHeader] No bit stream reader";
		*bitsUsed = 0;
		return(2);
	}//end if !bsr...

	///-------------------------- Addr of first macroblock -----------------------------------
	_slice._first_mb_in_slice = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Slice Type -------------------------------------------------
	_slice._type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	/// Limited implementation of slice types and modes for the Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_RSLH_NOMODE_READ;

	///-------------------------- Pic Param Set Id --------------------------------------------
	_slice._pic_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Frame Number ----------------------------------------------
	numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	_slice._frame_num = bsr->Read(numBits);
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		_slice._field_pic_flag = bsr->Read();
		bitsUsedSoFar++;
		if (_slice._field_pic_flag)
		{
			_slice._bottom_field_flag = bsr->Read();
			bitsUsedSoFar++;
		}//end if _field_pic_flag...
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		_slice._idr_pic_id = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		_slice._pic_order_cnt_lsb = bsr->Read(numBits);
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt_bottom = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...

	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		_slice._delta_pic_order_cnt[0] = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt[1] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		_slice._redundant_pic_cnt = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._direct_spatial_mv_pred_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::P_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._num_ref_idx_active_override_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._num_ref_idx_active_override_flag)
		{
			_slice._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
			{
				_slice._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._ref_pic_list_reordering_flag_l0 = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				_slice._reordering_of_pic_nums_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{
					_slice._abs_diff_pic_num_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._abs_diff_pic_num_minus1.
					goto H264V2_RSLH_NOMODE_READ;

				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{
					_slice._long_term_pic_num = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._long_term_pic_num.
					goto H264V2_RSLH_NOMODE_READ;

				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...
	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			_slice._no_output_of_prior_pics_flag = bsr->Read();
			_slice._long_term_reference_flag = bsr->Read();
			bitsUsedSoFar += 2;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if IDR_Slice...
		else
		{
			_slice._adaptive_ref_pic_marking_mode_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_RSLH_NOMODE_READ;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation  ---------------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._cabac_init_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	_slice._qp_delta = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::SI_Slice) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			_slice._sp_for_switch_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if SP_Slice...

		_slice._qs_delta = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		_slice._disable_deblocking_filter_idc = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			_slice._alpha_c0_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			_slice._beta_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _disable_deblocking_filter_idc...
	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_RSLH_NOMODE_READ;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSLH_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSLH_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RSLH_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSliceLayerHeader.

/** Write trailing bits to a bit stream.
A stop 1 bit is written and then zero bits are written until a byte boundary. Each
write checks if a bit overflow will occur before writing the stop bit. The zeros
are not counted in the bitsUsed. If the input stream param is NULL then this method
is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0.
*/
int H264v2Codec::WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	/// Write the stop bit.
	if (allowedBits < 1)
	{
		_errorStr = "H264V2:[WriteTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if allowedBits...
	if (bsw)
		bsw->Write(1);
	bitsUsedSoFar++;

	/// Write zeros to the end of the byte. Do not count the trailing zeros.
	if (bsw)
	{
		int toByteBoundary = (bsw->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Do not allow the last byte to be 0x00
			bsw->Write(toByteBoundary, 0);
		//bitsUsedSoFar += toByteBoundary;
	}//end if bsw...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}// end WriteTrailingBits.

/** Read trailing bits from the bit stream.
This impementation reads the trailing bit encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 3.
*/
int H264v2Codec::ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int bit = 1;

	if (remainingBits < 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if remainingBits...

	/// Read stop bit.
	if (bsr)
		bit = bsr->Read();
	bitsUsedSoFar++;
	if (bit != 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] No stop bit detected";
		*bitsUsed = bitsUsedSoFar;
		return(3);
	}//end if !stop bit...

	/// Read zeros up to the end of the byte. Do not count the trailing zeros.
	if (bsr)
	{
		int toByteBoundary = (bsr->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Only read zeros within the same byte as the stop bit.
		{
			bit = bsr->Read(toByteBoundary);
			//bitsUsedSoFar += toByteBoundary;
			if (bit != 0)
			{
				_errorStr = "H264V2:[ReadTrailingBits] Missing trailing zeros";
				*bitsUsed = bitsUsedSoFar;
				return(3);
			}//end if !zero bits...
		}//end if toByteBoundary...
	}//end if bsr...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadTrailingBits.

/** Insert start code emulation prevention codes.
Scan the entire stream, excluding the 32 bit actual start code, and check
for 24 bit 0x000000 - 0x000003 sequences. Replace them with 32 bit
0x00000300 - 0x00000303 sequences. The extra byte (8 bits) for each
emulation code is excluded from the number of allowed bits but is added
to the total consumed bits. [NB: Care must be taken when checking for
running out of bits to allow for these extra codes.] This method should
only be called once the entire frame has been encoded.
@param bsw	        : Stream to write into.
@param startOffset  : Start evaluating the stream from a byte offset.
@return			        : Return the number of extra bits inserted.
*/
int H264v2Codec::InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset)
{
	if (bsw == NULL)
		return(0);

	int count = 0;

	unsigned char*  streamHead = (unsigned char*)(bsw->GetStream());
	unsigned char*  stream = &(streamHead[startOffset]);

	/// It is assumed that the stream is fully encoded and the trailing bits have been added
	/// to ensure byte alignement of the stream. Therefore the current stream byte pos is the 
	/// number of encoded bytes in the stream.
	int  endPos = bsw->GetStreamBytePos() - 1 - startOffset;
	if (endPos < 2) return(0);

	/// Find the occurrance of the start code emulation then shift down by copying backwards from the end. Note
	/// that 1st 4 bytes are the start code 0x00000001.
	for (int pos = 6; pos <= endPos; pos++)
	{
		if ((stream[pos] & 0xFC) == 0) ///< Check for 0, 1, 2 or 3.
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0)) ///< Check 2 preceeding bytes are zero.
			{
				for (int i = endPos; i >= pos; i--) ///< Shift down by 1 byte.
					stream[i + 1] = stream[i];
				stream[pos] = 0x03; ///< Insert emulation prevention code.
				pos++;              ///< Continue from new shifted position.
				endPos++;           ///< Last byte is now shifted by 1 position.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end InsertEmulationPrevention.

/** Remove start code emulation prevention codes.
Scan the entire stream and check for 24 bit 0x000003 sequence
and remove the 0x03 byte from the stream. This method should
only be called once before decoding the entire frame.
@param bsr	: Stream to read from.
@return			: Return the number of extra bits removed.
*/
int H264v2Codec::RemoveEmulationPrevention(IBitStreamReader* bsr)
{
	if (bsr == NULL)
		return(0);

	int count = 0;

	unsigned char*  stream = (unsigned char*)(bsr->GetStream());
	int             bits = bsr->GetStreamBitSize();
	int             endPos = (bits / 8) - 1;
	if ((bits % 8) != 0)
		endPos++;

	/// Find the 1st occurrence of the emulation prevention code.
	int pos;
	for (pos = 2; pos <= endPos; pos++)
	{
		if (stream[pos] == 0x03) ///< Emulation prevention code = 0x03...
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0))  ///< ...and is preceeded by 2 zero bytes.
			{
				/// Shift remaining bytes up by 1 byte.
				for (int i = pos; i < endPos; i++)
					stream[i] = stream[i + 1];
				pos++;    ///< Skip one to prevent trapping a 0x00 followed by a 0x03 in the actual stream.
				endPos--; ///< Last byte was shifted by 1.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end RemoveEmulationPrevention.

/** Write the slice data layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes every macroblock encoding in top-left
to bottom-right order. Each write checks if a bit overflow will occur
before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is
used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int mb, i;
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// All macroblocks are written in order.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// ------------------------ Code the slice data -----------------------------------
	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		if (!pMb->_skip)	///< Encoding must set the _skip flag even for Intra macroblocks.
		{
			if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
				(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
			{
				/// ------------------------ Code the skip run -----------------------------------
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
				if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
					goto H264V2_VLCERROR_WRITE;
				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_RUNOUTOFBITS_WRITE;
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				bitsUsedSoFar += bitCount;

				_mb_skip_run = 0;	///< ...and reset.
			}//end if !I_Slice...

			/// ------------------------ Code the macroblock data ------------------------------------
			/// Only non-skipped macroblocks call this method.
			int ret = WriteMacroBlockLayer(bsw, pMb, allowedBits - bitsUsedSoFar, &bitCount);
			if (ret) ///< An error has occurred.
			{
				/// _errorStr was set in the WriteMacroBlockLayer() method.
				*bitsUsed = bitsUsedSoFar + bitCount;
				return(ret);
			}//end if ret...
			bitsUsedSoFar += bitCount;
		}//end if !_skip...
		else
		{
			_mb_skip_run++;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end else...

	}//end for mb...

	/// If the final macroblocks of the slice were all skipped then a skip run must be coded onto the stream.
	if (_mb_skip_run)
	{
		if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end if !I_Slice...
	}//end if _mb_skip_run...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceDataLayer.

/** Read the slice data layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int mb, i;
	int bitsUsedSoFar = 0;
	int numBits;

	/// Whip through each macroblock. Extract the encoded macroblock
	/// from the bit stream and vlc decode the vectors and coeff's.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// Get the first skip run from the stream for P slices.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_NOVLC_READ;
		bitsUsedSoFar += numBits;
		/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RUNOUTOFBITS_READ;
	}//end if !I_Slice...

	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		/// --------------- Decode the macroblock header from the stream ----------------------

		if (_mb_skip_run && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			pMb->_skip = 1;
			_mb_skip_run--;

			/// Skip implies a P_Skip macroblock type as Inter_16x16.
			pMb->_intraFlag = 0;
			pMb->_mb_type = MacroBlockH264::Inter_16x16;
			pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;
			/// Skip implies a single 16x16 (0,0) motion vector difference.
			pMb->_mvdX[MacroBlockH264::_16x16] = 0;
			pMb->_mvdY[MacroBlockH264::_16x16] = 0;
			/// Set the motion vector to the predicted value.
			if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
			{
				/// Force to zero.
				pMb->_mvX[MacroBlockH264::_16x16] = 0;
				pMb->_mvY[MacroBlockH264::_16x16] = 0;
			}//end if SkippedZeroMotionPredCondition...
			else
				pMb->GetMbMotionMedianPred(pMb, &(pMb->_mvX[MacroBlockH264::_16x16]), &(pMb->_mvY[MacroBlockH264::_16x16]));
			pMb->_coded_blk_pattern = 0;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _mb_skip_run...
		else
		{
			/// Macroblock not skipped and header must be extracted.
			pMb->_skip = 0;

			/// Macroblock type.
			_pMb[mb]._mb_type = _pMbTypeVlcDec->Decode(bsr);
			numBits = _pMbTypeVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
			/// Unpack _intraFlag and _mbPartPredMode from the decoded _mb_type.
			_pMb[mb].UnpackMbType(&(_pMb[mb]), _slice._type);

			/// Intra requires lum and chr prediction modes, Inter requires reference 
			/// index lists and motion vector diff values.
			if (!_pMb[mb]._intraFlag)	///< Inter	(most common option)
			{
				int numOfVecs = 1;
				// TODO: Implement other partition modes.
				if (_pMb[mb]._mbPartPredMode == MacroBlockH264::Inter_16x16)
					numOfVecs = 1;
				else
					goto H264V2_NOMODE_READ;
				for (int vec = 0; vec < numOfVecs; vec++)
				{
					/// Get the motion vector differences for this macroblock.
					_pMb[mb]._mvdX[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;

					_pMb[mb]._mvdY[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RUNOUTOFBITS_READ;

					/// Get the prediction vector from the neighbourhood.
					int predX, predY;
					_pMb[mb].GetMbMotionMedianPred(&(_pMb[mb]), &predX, &predY);
					_pMb[mb]._mvX[vec] = predX + _pMb[mb]._mvdX[vec];
					_pMb[mb]._mvY[vec] = predY + _pMb[mb]._mvdY[vec];
				}//end for vec...
			}//end if !_interFlag...
			else											/// Intra
			{
				// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

				/// Get chr prediction mode.
				_pMb[mb]._intraChrPredMode = _pMbIChrPredModeVlcDec->Decode(bsr);
				numBits = _pMbIChrPredModeVlcDec->GetNumDecodedBits();
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end else...

			/// If not Intra_16x16 mode then _coded_blk_pattern must be extracted.
			if ((_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!_pMb[mb]._intraFlag))
			{
				/// Block coded pattern.
				int isInter = 1;
				if (_pMb[mb]._intraFlag) isInter = 0;
				numBits = _pBlkPattVlcDec->Decode2(bsr, &(_pMb[mb]._coded_blk_pattern), &isInter);
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if !Intra_16x16...

		}//end else not skipped...

		/// Disassemble the bit pattern to determine which blocks are to be decoded.
		_pMb[mb].GetCodedBlockPattern(&(_pMb[mb]));

		/// For Inter modes and non-Intra_16x16 modes, delta qp is read only if there is at least one block 
		/// that has coeffs. The all zero coeff condition still requires the pattern to be decoded such that 
		/// zeros are loaded into the blocks.
		_pMb[mb]._mb_qp_delta = 0;	///< Default value required.
		if ((_pMb[mb]._coded_blk_pattern > 0) || (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16)))
		{
			/// Delta QP.
			_pMb[mb]._mb_qp_delta = _pDeltaQPVlcDec->Decode(bsr);
			numBits = _pDeltaQPVlcDec->GetNumDecodedBits();
			if (numBits == 0)
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if _coded_blk_pattern...

		int prevMbIdx = _pMb[mb]._mbIndex - 1;
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (_pMb[mb]._slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				_pMb[mb]._mbQP = _pMb[prevMbIdx]._mbQP + _pMb[mb]._mb_qp_delta;
			else
				_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;
		}//end if prevMbIdx...
		else
			_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;

		/// ------------------- Get the macroblock coeffs from the coded stream ---------------------
		int dcSkip = 0;
		int startBlk = 1;
		if (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16))
		{
			startBlk = 0;	///< Change starting block to include block num = -1;
			dcSkip = 1;
		}//end if Intra_16x16...
		/// For Lum blocks that are Inter coded and not Intra_16x16 coded the DC coeff is not skipped.
		for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
			_pMb[mb]._blkParam[i].dcSkipFlag = dcSkip;

		for (i = startBlk; i < MBH264_NUM_BLKS; i++)
		{
			/// Simplify the block reference.
			BlockH264* pBlk = _pMb[mb]._blkParam[i].pBlk;

			if (pBlk->IsCoded())
			{
				/// Choose the appropriate dimension CAVLC codec.
				IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
				if ((pBlk->GetHeight() == 4) && (pBlk->GetWidth() == 4))
					pCAVLC = _pCAVLC4x4;

				/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
				/// MB decodings in decoding order have already set the num of neighbourhood coeffs.
				int neighCoeffs = 0;
				if (_pMb[mb]._blkParam[i].neighbourIndicator)
				{
					if (_pMb[mb]._blkParam[i].neighbourIndicator > 0)
						neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pBlk);
					else	///< Negative values for neighbourIndicator imply pass through.
						neighCoeffs = _pMb[mb]._blkParam[i].neighbourIndicator;
				}//end if neighbourIndicator...
				pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
				pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, _pMb[mb]._blkParam[i].dcSkipFlag);

				numBits = pBlk->RleDecode(pCAVLC, bsr);					///< Vlc decode from the stream.
				if (numBits <= 0)	///< Vlc codec errors are detected from a negative return value.
				{
					if (numBits == -2)
						goto H264V2_RUNOUTOFBITS_READ;
					goto H264V2_NOVLC_READ;
				}//end if numBits...
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if IsCoded()...
			else
			{
				pBlk->SetNumCoeffs(0);	///< For future use.
				pBlk->Zero();
			}//end else...
		}//end for i...

		/// If end of skipped macroblocks then get the next skip run from the stream.
		if (!_mb_skip_run && !pMb->_skip && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All) && (mb != (len - 1)))
		{
			_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if !_mb_skip_run...

	}//end for mb...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Mode not supported";
	*bitsUsed = bitsUsedSoFar;
	return(3);
}//end ReadSliceDataLayer.

/** Write the macroblock layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes one non-skipped macroblock encoding.
Each write checks if a bit overflow will occur before writing. The check
is sufficiently frequent to warrant an early exit GOTO statement. If the
input stream param is NULL then this method is used to count the bits only.
@param bsw					: Stream to write into.
@param pMb					: Macroblock to encode.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;
	int dcSkip = 0;
	int startBlk = 1;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitCount = _pMbTypeVlcEnc->Encode(pMb->_mb_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_VLCERROR_WRITE_MB;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_RUNOUTOFBITS_WRITE_MB;
	if (bsw)
		bsw->Write(bitCount, _pMbTypeVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

		}//end for vec...
	}//end if !_intraFlag...
	else											/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitCount = _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pMbIChrPredModeVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitCount = _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pBlkPattVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitCount = _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pDeltaQPVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitCount = (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, bsw);
			if (bitCount <= 0)
			{
				if (bitCount == -2)
					goto H264V2_RUNOUTOFBITS_WRITE_MB;
				goto H264V2_VLCERROR_WRITE_MB;
			}//end if bitCount...
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			bitsUsedSoFar += bitCount;
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE_MB:
	/// Error info has contents loaded from outside of this method therefore concat is required.
	//strcat(_errorInfo, " H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture");
	//_errorStr = _errorInfo;
	_errorStr = "H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE_MB:
	_errorStr = "H264V2:[WriteMacroBlockLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteMacroBlockLayer.

/** Count the bits required to encode the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding. NB: No errors are checked.
@param pMb					: Macroblock to encode.
@return							: Total bit count.
*/
int H264v2Codec::MacroBlockLayerBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitsUsedSoFar = _pMbTypeVlcEnc->Encode(pMb->_mb_type);

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
		}//end for vec...
	}//end if !_intraFlag...
	else									/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitsUsedSoFar += _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitsUsedSoFar += _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitsUsedSoFar += _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerBitCounter.

/** Count the bits required to encode the coeffs at the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding excluding the headers. NB: No errors
are checked.
@param pMb	: Macroblock to encode.
@return			: Total bit count.
*/
int H264v2Codec::MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Ignore
  /// the header.

	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...

	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and accumulate the bit count. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerCoeffBitCounter.

/** Read the macroblock layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadMacroBlockLayer.

/** Apply the in-loop edge filter.
Used in both the encoder and decoder to remove blocking artefacts on the 4x4 boundary
edges. It is applied macroblock by macroblock in raster scan order to the reference
images of both the Lum and Chr components.
@return	:	none.
*/
void H264v2Codec::ApplyLoopFilter(void)
{
	int mb, i, j;
	short** lumRef = _RefLum->Get2DSrcPtr();	///< Image space to operate on.
	short** cbRef = _RefCb->Get2DSrcPtr();
	short** crRef = _RefCr->Get2DSrcPtr();

	for (mb = 0; mb < _mbLength; mb++)
	{
		MacroBlockH264* pMb = &(_pMb[mb]);
		MacroBlockH264* aboveMb = _pMb[mb]._aboveMb;
		MacroBlockH264* leftMb = _pMb[mb]._leftMb;

		/// All macroblock boundaries that have intra neighbours use
		/// boundary strength = {3, 4}. Vertical filtering first.

		///---------------- Vertical Edges --------------------------------------
		if (leftMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || leftMb->_intraFlag)	///< Left intra macroblock boundary (bS = 4).
			{
				for (i = 0; i < 16; i += 4)
					VerticalFilter(pMb, lumRef, 1, i, 0, 4, 4);
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, 0, 4, 4);
					VerticalFilter(pMb, crRef, 0, i, 0, 4, 4);
				}//end for i...
			}//end if _intraFlag...
			else																	///< Left inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 vector is used
				// per macroblock and from the same single reference. Boundary 4x4 blocks 
		// are compared with the neighbouring macroblock motion vectors.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - leftMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - leftMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (i = 0; i < 4; i++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[i][0].GetNumCoeffs() || pMb->_lumBlk[i][0]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, 0, 4, bS);	///< At (row = 4*i, col = 0) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						VerticalFilter(pMb, cbRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
						VerticalFilter(pMb, crRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
					}//end if bS...
				}//end for i...

			}//end else...
		}//end if leftMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (j = 4; j < 16; j += 4)
				for (i = 0; i < 16; i += 4)	///< All rows first for each col.
					VerticalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (j = 4; j < 8; j += 4)
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, j, 4, 3);
					VerticalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for j & i...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (j = 1; j < 4; j++)
				for (i = 0; i < 4; i++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (j == 2)
						{
							VerticalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
							VerticalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
						}//end if j...
					}//end if bS...

				}//end for j & i...
		}//end else...

		///---------------- Horizontal Edges -------------------------------------
		if (aboveMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || aboveMb->_intraFlag)	///< Above intra macroblock boundary. (bS = 4)
			{
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, 0, j, 4, 4);
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, 0, j, 4, 4);
					HorizontalFilter(pMb, crRef, 0, 0, j, 4, 4);
				}//end for j...
			}//end if _intraFlag...
			else																	///< Above inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 motion vector is used
				// per macroblock and from the same single reference.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - aboveMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - aboveMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (j = 0; j < 4; j++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[0][j].GetNumCoeffs() || pMb->_lumBlk[0][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						HorizontalFilter(pMb, lumRef, 1, 0, j << 2, 4, bS);	///< At (row = 0, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						HorizontalFilter(pMb, cbRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
						HorizontalFilter(pMb, crRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
					}//end if bS...
				}//end for j...

			}//end else...
		}//end aboveMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (i = 4; i < 16; i += 4)
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (i = 4; i < 8; i += 4)
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, i, j, 4, 3);
					HorizontalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for i & j...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (i = 1; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						HorizontalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (i == 2)
						{
							HorizontalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
							HorizontalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
						}//end if i...
					}//end if bS...

				}//end for i & j...
		}//end else...

	}//end for mb...

}//end ApplyLoopFilter.

/** Apply the in-loop deblocking filter to vertical block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one column with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations down the col from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + pMb->_leftMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_leftMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY + i][offX - 1] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY + i][offX] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX - 2] = (short)(p1 + delta);		                ///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX + 1] = (short)(q1 + delta);		                ///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be colOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX - 1] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY + i][offX - 2] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY + i][offX - 3] = (short)(((2 * (int)(img[offY + i][offX - 4])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX - 1] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + i][offX + 1] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + i][offX + 2] = (short)(((2 * (int)(img[offY + i][offX + 3])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end VerticalFilter.

/** Apply the in-loop deblocking filter to horizontal block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one row with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations along the row from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + pMb->_aboveMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_aboveMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY - 1][offX + i] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY][offX + i] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY - 2][offX + i] = (short)(p1 + delta);			///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + 1][offX + i] = (short)(q1 + delta);			///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be rowOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY - 1][offX + i] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY - 2][offX + i] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY - 3][offX + i] = (short)(((2 * (int)(img[offY - 4][offX + i])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY - 1][offX + i] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY][offX + i] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + 1][offX + i] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + 2][offX + i] = (short)(((2 * (int)(img[offY + 3][offX + i])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY][offX + i] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end HorizontalFilter.

/** Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		short*			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i]);	///< Short cuts.
		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);

		/// Transform without scaling or quant.
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][0]
		*pDcLumBlk++ = pLumBlk->GetDC(); ///< Set the Lum DC block from the DC term of this block and scale it without rounding.
		(pLumBlk++)->SetDC(0); ///< Required to ensure the feedback loop operates properly.

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][1]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][2]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][3]
		*pDcLumBlk = pLumBlk->GetDC();
		pLumBlk->SetDC(0);

		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][3]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][2]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][1]
		pLumBlk->Quantise(_pF4x4TLum);			///< [i][0]
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantIntra16x16MBlk.

/** Transform and Quantise an Intra_16x16 macroblock to below a max distortion criterion.
This overload method decrements the mb QP value from its existing value until the mb distortion
drops below the specified Dmax value. It returns the distortion at the final value of QP that
meets the criterion and places the decoded mb values in the temp blks. The final inverse decoded
blks are stored in the tmp blks.
@param pMb	  : Macroblock to transform.
@param Dmax   : Target max distortion criterion.
@param minQP  : Lowest QP value allowed.
@return			  : Lum distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int qp = pMb->_mbQP;
	int distortion = 0;

	///------------ Lum in raster scan order--------------------------

	  /// Transform without quant to extract the DC term. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);

			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);   ///< DCT.
			*pDcLumBlk++ = pb->GetDC();         ///< Set DC blk
			pb->SetDC(0);                       ///< Clear DC term in AC blk.
		}//end for i & j...

		/// Transform the DC blocks.
	_pFDC4x4T->SetMode(IForwardTransform::TransformOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	/// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);
		_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			}//end for i & j...

			/// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

		/// For QP = H264V2_MAX_QP it is likely that all coeffs are zeros. Find the QP value 
		/// that results in at least 1 non-zero coeff.
	//    if(qp == H264V2_MAX_QP)
	//      qp = GetQPtoNonZeroCoeff(pMb, minQP);

		/// Inverse quant and inverse transform the DC blks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

		/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
		distortion = 0;
		short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to DC blk.
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
				pb->InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
				pb->SetDC(*pDcLumBlkTmp++);       ///< Load the DC term from the DC blk.

				_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
				pb->InverseTransform(_pI4x4TLum); ///< Inverse transform.

				/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

		/// Update mb QP.
		pMb->_mbQP = qp;
		/// New qp.
		qp -= 4; //MbStepSize[qp];
		if (qp < minQP) qp = minQP;

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the main lum AC and DC blks.
	_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
		}//end for i & j...
	_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	///----------- Chr in raster scan order --------------------------

	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...

	  /// Restore state.
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	pMb->_mbEncQP = pMb->_mbQP;

	return(distortion);
}//end TransAndQuantIntra16x16MBlk.

/** Code refactoring for TransAndQuantIntra16x16MBlk() method.
Get the mb QP value such that there is at least one non-zero DCT coeff.
@param pMb	  : Macroblock to transform.
@return       : QP value for non-zero coeffs.
*/
int H264v2Codec::GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP)
{
	int i, j;
	int qp = H264V2_MAX_QP;

	/// Are all coeffs zeros?
	int isZero = pMb->_lumDcBlkTmp.IsZero2();
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			isZero &= pMb->_lumBlkTmp[i][j].IsZero2();
	if (isZero)
	{
		/// Re-quant at QP = 1.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, 1);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);

		/// Find the blk and position of the peak peak value.
		BlockH264*  pPeakBlk = &(pMb->_lumDcBlkTmp);
		short*      pB = pPeakBlk->GetBlk();
		int         peakPos = 0;
		short       peakVal = abs(pB[0]);

		for (i = 1; i < 16; i++) ///< DC blk.
		{
			if (abs(pB[i]) > peakVal)
			{
				peakPos = i;
				peakVal = abs(pB[i]);
			}//end if pB[]...
		}//end for i...

		for (i = 0; i < 4; i++)  /// AC blks.
			for (j = 0; j < 4; j++)
			{
				pB = pMb->_lumBlkTmp[i][j].GetBlk();
				for (int k = 0; k < 16; k++)
				{
					if (abs(pB[k]) > peakVal)
					{
						peakPos = k;
						peakVal = abs(pB[k]);
						pPeakBlk = &(pMb->_lumBlkTmp[i][j]);
					}//end if abs(pB[])...
				}//end for k...
			}//end for i & j...

		  /// Get the pre-quant value from the main blks in the position required.
		short val = (pPeakBlk->GetBlk())[peakPos];
		IForwardTransform* pQuantiser = _pF4x4TLum;
		if (pPeakBlk->IsDc())
			pQuantiser = _pFDC4x4T;

		/// Quantise this single peak value until it is non-zero.
		qp = H264V2_MAX_QP - 1;
		while ((qp > minQP) && (pQuantiser->QuantiseValue(val, peakPos, qp) == 0))
		{
			qp -= MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end while qp...

		/// Re-load and quantise the whole mb at this new QP value.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			  /// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

	}//end if isZero...

	return(qp);
}//end SetQPtoNonZeroCoeff.

/** Transform and Quantise an Intra_16x16 macroblock with Inverse.
This method provides a speed improvement for macroblock processing and code refactoring. The
inverse transform and distortion measurment is included to the temp blks.
@param pMb	  : Macroblock to transform.
@param withD  : Include distortion calculation.
@return			  : distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD)
{
	int i, j;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	int distortion = 0;

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method. The DC blocks are in the TransformAndQuant mode.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);

	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
  /// Copy the coeffs to the temp blks and do the inverse process.

  ///------------ Lum in raster scan order--------------------------

	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			if (withD)
				pMb->_lumBlk[i][j].Copy(_tmpBlk[i][j].GetBlk());

			_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
			pMb->_lumBlk[i][j].ForwardTransform(_pF4x4TLum);  ///< DCT.
			pDcLumBlk[i * 4 + j] = pMb->_lumBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_lumBlk[i][j].SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TLum->SetMode(IForwardTransform::QuantOnly); ///< Scale and quant.
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);

		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Copy the Lum blks into the temp Lum blks for inverse transform + quant processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

	/// Inverse quant and inverse transform the temp DC blks.
	pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

	/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
	short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to temp DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
			pMb->_lumBlkTmp[i][j].InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
			pMb->_lumBlkTmp[i][j].SetDC(pDcLumBlkTmp[4 * i + j]); ///< Load the DC term from the DC blk.

			_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
			pMb->_lumBlkTmp[i][j].InverseTransform(_pI4x4TLum); ///< Inverse transform.

			/// Total square diff with the input store.
			if (withD)
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
		}//end for i & j...

  /// Region of interest multiplier application to the whole mb.
  distortion = ROIDistortion(pMb->_mbIndex, distortion);

  ///----------- Chr in raster scan order --------------------------

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pMb->_cbBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCbBlk[i * 2 + j] = pMb->_cbBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_cbBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			/// Cr
			pMb->_crBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCrBlk[i * 2 + j] = pMb->_crBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_crBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pMb->_cbBlk[i][j].Quantise(_pF4x4TChr);         ///< Scale and quant.
			pMb->_crBlk[i][j].Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pMb->_cbBlkTmp[i][j].InverseQuantise(_pI4x4TChr); ///< Inverse scale and quant.
			pMb->_cbBlkTmp[i][j].SetDC(pDcCbBlkTmp[2 * i + j]); ///< Load the DC term from the DC blk.
			pMb->_crBlkTmp[i][j].InverseQuantise(_pI4x4TChr);
			pMb->_crBlkTmp[i][j].SetDC(pDcCrBlkTmp[2 * i + j]);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pMb->_cbBlkTmp[i][j].InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pMb->_crBlkTmp[i][j].InverseTransform(_pI4x4TChr);
		}//end for i & j...

	return(distortion);
}//end TransAndQuantIntra16x16MBlkWithInv.

/** Transform and Quantise an Intra_16x16 mode block.
Code refactoring method to transform the block and store the DC coeff before quantisation. The
transform must have the quantisation parameter preset before calling this method.
@param pTQ					: Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to store the DC coeff.
@return							: none.
*/
void H264v2Codec::TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IForwardTransform::TransformOnly);
	pBlk->ForwardTransform(pTQ);
	*pDcBlkCoeff = pBlk->GetDC();	///< Set the DC block from the DC term of this block.
	pBlk->SetDC(0);								///< Required to ensure the feedback loop operates properly.
	pTQ->SetMode(IForwardTransform::QuantOnly);
	pBlk->Quantise(pTQ);
}//end TransAndQuantIntra16x16ModeBlk.

/** Inverse Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks to temp blks.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, 0, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlk.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		short*			pDcLumBlk;
		BlockH264*	pLumBlk;

		/// Unroll the inner loop.

		if (tmpBlkFlag)
		{
			pDcLumBlk = &((pMb->_lumDcBlkTmp.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlkTmp[i][0]);
		}//end if tmpBlkFlag...
		else
		{
			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlk[i][0]);
		}//end else...

		/// Inverse scale and quant.
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][2]
		pLumBlk->InverseQuantise(_pI4x4TLum);			///< [i][3]
		_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform without scaling or quant.
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);

		pLumBlk->SetDC(*pDcLumBlk--);						///< Load the DC term from the DC block.
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][3]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][2]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][1]

		pLumBlk->SetDC(*pDcLumBlk);
		pLumBlk->InverseTransform(_pI4x4TLum);			///< [i][0]

		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantIntra16x16MBlk.

/** Inverse Quantise and Transform an Intra_16x16 mode block.
Code refactoring method to inverse quantise the block and set the DC coeff before the inverse
transform. The inverse transform must have the quantisation parameter preset before calling
this method.
@param pTQ					: Inverse Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to get the DC coeff.
@return							: none.
*/
void H264v2Codec::InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IInverseTransform::QuantOnly);
	pBlk->InverseQuantise(pTQ);
	pBlk->SetDC(*pDcBlkCoeff);	///< Set the DC coeff for this block from the DC block.
	pTQ->SetMode(IInverseTransform::TransformOnly);
	pBlk->InverseTransform(pTQ);
}//end InvTransAndQuantIntra16x16ModeBlk.

/** Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the chr 4x4 AC blocks in this method. The lum and DC blocks are in the 
  /// TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetMode(IForwardTransform::TransformAndQuant);
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each chr block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);	///< Short cuts.

		/// Transform Lum with scaling and quant.
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][0]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][1]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][2]
		pLumBlk->ForwardTransform(_pF4x4TLum);			///< [i][3]

	/// For chr, split the transform and quant processes. 
		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant chr.
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantInter16x16MBlk.

/** Transform and Quantise an Inter_16x16 macroblock with a Dmax criterion.
This method provides a speed improvement for macroblock processing and code refactoring. The
QP value is decremented until the mb Lum distortion is below Dmax. The quatised coeff are stored
in the _lumBlk[][], etc. and the inverse reconstructed pels are stored in the _lumBlkTmp[][], etc.
@param pMb	  : Macroblock to transform.
@param Dmax   : Max distortion for this mb.
@param minQP  : Lower limit for the QP descent.
@return			  : Distortion for the mb.
*/
int H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int distortion = 0;
	int qp = pMb->_mbQP;
	int eqp = pMb->_mbEncQP;
	if (eqp > (H264V2_MAX_QP + 16))  ///< Only consider lum coeffs.
		eqp = H264V2_MAX_QP + 16;

	/// ----------------------------- Lum -----------------------------------------------------------
	/// Transform without quant and store. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the motion pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);
		}//end for i & j...

	  /// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	  /// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_0_0, MBH264_LUM_3_3);

		/// Quant only for the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		/// Invese quant and transform.
		_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);

		/// Forward quant and inverse quant and transform. Accumulate distortion.
		distortion = 0;
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				pb->ForwardTransform(_pF4x4TLum); ///< Forward quant.
				/// For extended EncQP range [52..67], zero coeffs.
				if (eqp > H264V2_MAX_QP)
					pb->Zero(16 - (eqp - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);

				pb->InverseTransform(_pI4x4TLum);	///< Inverse scale, quant and transform.
			/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

    /// Update mb QP.
		pMb->_mbQP = qp;
		pMb->_mbEncQP = eqp;
		/// New qp.
		if (eqp > H264V2_MAX_QP)
		{
			eqp -= 4;
			if (eqp < H264V2_MAX_QP) eqp = H264V2_MAX_QP;
		}//end if eqp...
		else
		{
			qp -= 4; //MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end else...

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the lum blks.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			/// Zero coeffs for extended EncQP range.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
				pMb->_lumBlk[i][j].Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
		}//end for i & j...

	  /// ----------------------------- Chr -----------------------------------------------------------
	  /// Chr is processed after the QP value for this block has been determined by the Lum process.
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);

			/// Follow the lum extended QP range on the Chr AC coeffs.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
			{
				pCb->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
				pCr->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
			}//end if _mbEncQP...
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...


	return(distortion);
}//end TransAndQuantInter16x16MBlk.

/** Inverse Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to inverse transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pLumBlk;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks, excluding Lum DC blk, to temp blks.
		MacroBlockH264::CopyBlksToTmpBlksCoeffOnly(pMb, 1, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Lum & Chr components.
		pLumBlk = &(pMb->_lumBlkTmp[0][0]);
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pLumBlk = &(pMb->_lumBlk[0][0]);
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		/// Unroll the inner loop.

		/// Inverse scale, quant and transform Lum.
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][2]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][3]

	/// Inverse scale and quant first for Chr.
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform after scaling and quant.
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantInter16x16MBlk.

/** Get Intra Lum prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref lum img and write it to the pred parameter. Used by the encoder. Return the
intra_16x16 prediction mode.
@param pMb				: Macroblock to predict.
@param in					: Lum input image.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred)
{
	int i, j;
	int a, b, c;	///< Plane mode intermediates.
	int predDC;	///< Other mode intermediates.
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_16x16_DC;

	short**	in2D = in->Get2DSrcPtr();
	int			iOffX = in->GetOriginX();
	int			iOffY = in->GetOriginY();
	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Plane mode preparation --------------------------------------
		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
			V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
		}//end for i...
		b = (5 * H + 32) >> 6;
		c = (5 * V + 32) >> 6;
		a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_16x16_Plane] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], H264V2_CLIP255((a + b*(x - 7) + c*(y - 7) + 16) >> 5));
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 3; i++)	///< Total of 3 modes. Plane mode excluded.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY + i][rOffX - 1];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Horiz;	///< MacroBlockH264::Intra_16x16_Horiz = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Horiz])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY - 1][rOffX + i];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Vert])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Lum value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		pred->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
		pred->Fill(predDC);
		break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
	}//end Horiz block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra16x16LumPredAndMode.

/** Get Intra Lum prediction.
Apply the prediction mode specified to predict from the ref lum img and write it to the pred
parameter. Used by the decoder.
@param pMb				: Macroblock to predict.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@param predMode		: Mode to apply.
@return						: 1 = success, 0 = failure.
*/
int H264v2Codec::GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode)
{
	int i, j;

	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Fill the prediction block with the appropriate mode prediction.
	switch (predMode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		if (pMb->_aboveMb != NULL)	///< Vert prediction only cares about the macroblock above.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
		}//end if aboveMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		if (pMb->_leftMb != NULL)	///< Horiz prediction only cares about the macroblock to the left.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
		}//end if leftMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
	{
		bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);
		bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);
		bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);

		int predDC = 0;
		if (aboveAndLeft)
		{
			for (i = 0; i < 16; i++)
				predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
			predDC = (predDC + 16) >> 5;
		}//end if aboveAndLeft...
		else if (leftOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY + i][rOffX - 1];
			predDC = (predDC + 8) >> 4;
		}//end else if leftOnly...
		else if (aboveOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY - 1][rOffX + i];
			predDC = (predDC + 8) >> 4;
		}//end else if aboveOnly...
		else
		{
			predDC = 128;	///< Half the max value.
		}//end else...

		pred->Fill(predDC);
	}//end DC block...
	break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);

		if (all)	///< All the neighbouring macroblocks must be available for prediction.
		{
			int		H = 0;
			int		V = 0;
			for (i = 0; i < 8; i++)
			{
				H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
				V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
			}//end for i...
			int b = (5 * H + 32) >> 6;
			int c = (5 * V + 32) >> 6;
			int a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
		}//end if all...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	}//end switch predMode...

	return(1);
}//end GetIntra16x16LumPred.

/** Get Intra Lum DC prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int dirCnt = 0;
	int predValue = 0;

	short** img = lum->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offLumX;
		offY = pMb->_aboveMb->_offLumY + 15;
		for (i = 0; i < 16; i++)
			predValue += img[offY][offX + i];
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offLumX + 15;
		offY = pMb->_leftMb->_offLumY;
		for (i = 0; i < 16; i++)
			predValue += img[offY + i][offX];
	}//end if _leftMb...

	/// Set the accumulated DC prediction value.
	if (dirCnt == 2)
		predValue = (predValue + 16) >> 5;
	else if (dirCnt == 1)
		predValue = (predValue + 8) >> 4;
	else
		predValue = 128;	///< Half max Lum value.

	pred->Fill(predValue);

}//end GetIntra16x16LumDCPred.

/** Get Intra Lum Plane prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction. The H.264 std does not specify
this last case for Plane pred.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = lum->Get2DSrcPtr();
		int			iOffX = lum->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = lum->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 8 + i] - (int)img2D[iOffY - 1][iOffX + 6 - i]);
			V += (i + 1)*((int)img2D[iOffY + 8 + i][iOffX - 1] - (int)img2D[iOffY + 6 - i][iOffX - 1]);
		}//end for i...
		int b = (5 * H + 32) >> 6;
		int c = (5 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 15][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 15]) << 4;

		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
			{
				short x = (short)((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra16x16LumPlanePred.

/** Get Intra Vertical prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prediction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i;
	MacroBlockH264* amb = pMb->_aboveMb;

	if (amb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last row of the macroblock above.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = amb->_offLumX;
			iOffY = amb->_offLumY + (img->GetHeight() - 1);
		}//end if lumFlag...
		else
		{
			iOffX = amb->_offChrX;
			iOffY = amb->_offChrY + (img->GetHeight() - 1);
		}//end else...
		short* ps = &(img2D[iOffY][iOffX]);
		for (i = 0; i < height; i++)	///< Rows.
			memcpy((void *)(&(pred2D[offY + i][offX])), (const void *)ps, byteLen);
		return(1);
	}//end if amb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Macroblock above does not exist.
}//end GetIntraVertPred.

/** Get Intra Horizontal prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prodiction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i, j;
	MacroBlockH264* lmb = pMb->_leftMb;

	if (lmb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last col of the macroblock to the left.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = lmb->_offLumX + (img->GetWidth() - 1);
			iOffY = lmb->_offLumY;
		}//end if lumFlag...
		else
		{
			iOffX = lmb->_offChrX + (img->GetWidth() - 1);
			iOffY = lmb->_offChrY;
		}//end else...
		for (i = 0; i < height; i++)	///< Rows.
		{
			short* pd = &(pred2D[offY + i][offX]);
			short  x = img2D[iOffY + i][iOffX];
			for (j = 0; j < width; j++)
				*pd++ = x;
		}//end for i...
		return(1);
	}//end if lmb...

	/// Safety precaution not defined in H.264 standard. If the left macroblock
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Left macroblock does not exist.
}//end GetIntraHorizPred.

/** Get Intra Chr prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref chr img and write it to the pred parameter. Used by the encoder. Return the
intra_8x8 prediction mode.
@param pMb				: Macroblock to predict.
@param cb					: Cb Chr input image.
@param cr					: Cr Chr input image.
@param refCb			: Reference chr Cb img to predict from.
@param refCr			: Reference chr Cr img to predict from.
@param predCb			: 8x8 Cb overlay to write result to.
@param predCr			: 8x8 Cr overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
	OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr,
	OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr)
{
	int i, j;
	int aCb, bCb, cCb, aCr, bCr, cCr;	///< Plane mode intermediates.
	int predCbDC[4] = { 0, 0, 0, 0 };	///< DC mode intermediates.
	int predCrDC[4] = { 0, 0, 0, 0 };
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_Chr_DC;

	short**	inCb2D = cb->Get2DSrcPtr();
	short**	inCr2D = cr->Get2DSrcPtr();
	int			iOffX = cb->GetOriginX();	///< Assume Cb and Cr have the same offsets.
	int			iOffY = cb->GetOriginY();
	short**	refCb2D = refCb->Get2DSrcPtr();
	short**	refCr2D = refCr->Get2DSrcPtr();
	int			rOffX = refCb->GetOriginX();
	int			rOffY = refCb->GetOriginY();
	short**	predCb2D = predCb->Get2DSrcPtr();
	short**	predCr2D = predCr->Get2DSrcPtr();
	int			pOffX = predCb->GetOriginX();
	int			pOffY = predCr->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Plane mode preparation --------------------------------------
		int		HCb = 0;
		int		VCb = 0;
		int		HCr = 0;
		int		VCr = 0;
		for (i = 0; i < 4; i++)
		{
			HCb += (i + 1)*((int)refCb2D[rOffY - 1][rOffX + 4 + i] - (int)refCb2D[rOffY - 1][rOffX + 2 - i]);
			VCb += (i + 1)*((int)refCb2D[rOffY + 4 + i][rOffX - 1] - (int)refCb2D[rOffY + 2 - i][rOffX - 1]);
			HCr += (i + 1)*((int)refCr2D[rOffY - 1][rOffX + 4 + i] - (int)refCr2D[rOffY - 1][rOffX + 2 - i]);
			VCr += (i + 1)*((int)refCr2D[rOffY + 4 + i][rOffX - 1] - (int)refCr2D[rOffY + 2 - i][rOffX - 1]);
		}//end for i...
		bCb = (34 * HCb + 32) >> 6;
		cCb = (34 * VCb + 32) >> 6;
		aCb = ((int)refCb2D[rOffY + 7][rOffX - 1] + (int)refCb2D[rOffY - 1][rOffX + 7]) << 4;
		bCr = (34 * HCr + 32) >> 6;
		cCr = (34 * VCr + 32) >> 6;
		aCr = ((int)refCr2D[rOffY + 7][rOffX - 1] + (int)refCr2D[rOffY - 1][rOffX + 7]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_Chr_Plane] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCb + bCb*(x - 3) + cCb*(y - 3) + 16) >> 5))) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCr + bCr*(x - 3) + cCr*(y - 3) + 16) >> 5))));
		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 3; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY + i][rOffX - 1];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];

			predCrDC[0] += (int)refCr2D[rOffY + i][rOffX - 1];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[1] = predCbDC[0];
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = predCbDC[2];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[1] = predCrDC[0];
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = predCrDC[2];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (y > 3)
				partition = 2;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Horiz] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Horiz;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY - 1][rOffX + i];
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];

			predCrDC[0] += (int)refCr2D[rOffY - 1][rOffX + i];
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[2] = predCbDC[0];
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[3] = predCbDC[1];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[2] = predCrDC[0];
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[3] = predCrDC[1];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (x > 3)
				partition = 1;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));

		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Vert] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Vert;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Chr value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		predCb->Fill(128);
		predCr->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_Chr_DC:
	{
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = predCbDC[0];
				predCb2D[pOffY + i][pOffX + 4 + j] = predCbDC[1];
				predCb2D[pOffY + 4 + i][pOffX + j] = predCbDC[2];
				predCb2D[pOffY + 4 + i][pOffX + 4 + j] = predCbDC[3];

				predCr2D[pOffY + i][pOffX + j] = predCrDC[0];
				predCr2D[pOffY + i][pOffX + 4 + j] = predCrDC[1];
				predCr2D[pOffY + 4 + i][pOffX + j] = predCrDC[2];
				predCr2D[pOffY + 4 + i][pOffX + 4 + j] = predCrDC[3];
			}//end for i & j...
	}//end DC block...
	break;
	case MacroBlockH264::Intra_Chr_Horiz:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY + i][rOffX - 1];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY + i][rOffX - 1];
			}//end i & j...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_Chr_Vert:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY - 1][rOffX + j];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY - 1][rOffX + j];
			}//end for i & j...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_Chr_Plane:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCb + bCb*(j - 3) + cCb*(i - 3) + 16) >> 5);
				predCr2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCr + bCr*(j - 3) + cCr*(i - 3) + 16) >> 5);
			}//end for i & j...
	}//end Plane block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra8x8ChrPredAndMode.

/** Get Intra Chr DC prediction.
Predict from the parameter Chr img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use the
mid chr value (128) as the prediction. The H.264 std does not specify
this last case for DC pred.
@param pMb				: Macroblock to transform.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int predValue[4];
	int dirCnt = 0;
	int sum[4] = { 0, 0, 0, 0 };

	short** img = chr->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offChrX;
		offY = pMb->_aboveMb->_offChrY + 7;
		for (i = 0; i < 4; i++)
		{
			sum[0] += img[offY][offX + i];
			sum[1] += img[offY][offX + 4 + i];
		}//end for i...
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offChrX + 7;
		offY = pMb->_leftMb->_offChrY;
		for (i = 0; i < 4; i++)
		{
			sum[2] += img[offY + i][offX];
			sum[3] += img[offY + 4 + i][offX];
		}//end for i...
	}//end if _leftMb...

	/// Set the accumulated DC prediction values.
	if (dirCnt == 2)
	{
		predValue[0] = (sum[0] + sum[2] + 4) >> 3;
		predValue[1] = (sum[1] + 2) >> 2;
		predValue[2] = (sum[3] + 2) >> 2;
		predValue[3] = (sum[1] + sum[3] + 4) >> 3;
	}//end if dirCnt...
	else if (dirCnt == 1)
	{
		if (pMb->_leftMb == NULL)
		{
			predValue[0] = (sum[0] + 2) >> 2;
			predValue[1] = (sum[1] + 2) >> 2;
			predValue[2] = (sum[0] + 2) >> 2;
			predValue[3] = (sum[1] + 2) >> 2;
		}//end if !leftMb...
		else
		{
			predValue[0] = (sum[2] + 2) >> 2;
			predValue[1] = (sum[2] + 2) >> 2;
			predValue[2] = (sum[3] + 2) >> 2;
			predValue[3] = (sum[3] + 2) >> 2;
		}//end else...
	}//end else if dirCnt...
	else
	{
		/// Mid Chr value.
		predValue[0] = 128;
		predValue[1] = 128;
		predValue[2] = 128;
		predValue[3] = 128;
	}//end else...

	int xBase = pred->GetOriginX();
	int yBase = pred->GetOriginY();
	pred->SetOverlayDim(4, 4);
	for (int y = 0, i = 0; y < 2; y++)
		for (int x = 0; x < 2; x++, i++)
		{
			pred->SetOrigin(xBase + x * 4, yBase + y * 4);
			pred->Fill(predValue[i]);
		}//end for y & x...

	/// Put the block back into shape.
	pred->SetOverlayDim(8, 8);
	pred->SetOrigin(xBase, yBase);

}//end GetIntra8x8ChrDCPred.

/** Get Intra Chr Plane prediction.
Predict from the parameter Chr img and write it to the pred parameter. This
implementation if for YCbCr 4:2:0 chroma_format_idc = 1 only. If there are
no valid neighbours to make the prediction then use the mid chr value (128)
as the prediction. The H.264 std does not specify this last case for DC pred.
@param pMb				: Macroblock to predict.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = chr->Get2DSrcPtr();
		int			iOffX = chr->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = chr->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 4; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 4 + i] - (int)img2D[iOffY - 1][iOffX + 2 - i]);
			V += (i + 1)*((int)img2D[iOffY + 4 + i][iOffX - 1] - (int)img2D[iOffY + 2 - i][iOffX - 1]);
		}//end for i...
		int b = (34 * H + 32) >> 6;
		int c = (34 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 7][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 7]) << 4;

		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				short x = (short)((a + b*(j - 3) + c*(i - 3) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra8x8ChrPlanePred.

/*
-----------------------------------------------------------------------
  Private nested classes.
-----------------------------------------------------------------------
*/
/** Encode the image data for Intra IDR pictures.
Process all slices and their macroblocks in order. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
#ifdef H264V2_DUMP_MB_RD_DATA

		if ((mb > 66) && (_codec->_mbRDTablePos < 65)) ///< Collect data for 64 mbs starting in the 3rd mb row of the image.
		{
			/// Write the mb number in row 0.
			_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, 0, mb);

			int qp;
			for (qp = 1; qp < _codec->_mbRDTableLen; qp++)
			{
				_codec->_pMb[mb]._mbQP = qp;
				_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 2);  ///< D only.

				_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, qp, _codec->_pMb[mb]._distortion[qp]);
			}//end for qp...

			_codec->_mbRDTablePos++;  ///< Represents columns. 
		}//end if mb...

#endif /// H264V2_DUMP_MB_RD_DATA

		_codec->_pMb[mb]._mbQP = _codec->_slice._qp;
		_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 0);
	}//end for mb...

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplStdVer1::Encode.

/** Decode of the Intra macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		/// --------------------- Inverse Transform & Quantisation --------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			_codec->InverseTransAndQuantIntra16x16MBlk(pMb, 0);

		/// --------------------- Image Prediction and Storing -------------------------------------
		/// From the prediction mode settings, make the appropriate prediction macroblock and then
		/// add the inverse transformed and quantised values to it. Fill the image (difference) colour 
		/// components from all the non-DC 4x4 blks (i.e. Not blks = -1, 17, 18) of the macroblock blocks.

		/// Store blocks into ref img.
		MacroBlockH264::StoreBlks(pMb, _codec->_RefLum, lOffX, lOffY, _codec->_RefCb, _codec->_RefCr, cOffX, cOffY, 0);

		/// Predict the output from the previously decoded neighbour ref macroblocks.
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.

		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			_codec->GetIntra16x16LumDCPred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			_codec->GetIntra16x16LumPlanePred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		}//end switch _intra16x16PredMode...

		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);

		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraHorizPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraVertPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		}//end switch _intraChrPredMode...

		/// --------------------- Add the prediction -----------------------------------------------
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY);           ///< Align the Ref Lum img block with this macroblock.
		_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add pred to ref Lum and leave result in ref img.
		/// Cb.
		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
		/// Cr.
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

	}//end for mb...

	return(1);
}//end IntraImgPlaneDecoderImplStdVer1::Decode.

/** Encode the image data for Intra pictures with adaptive PQ (minmax).
The encoder seeks to find the optimal quant value for each macroblock using a minmax algorithm with
the constraint of a max number of bits specified in the method parameter list by allowedBits.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: 1/0 = do/do not update ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int len = _codec->_mbLength;
	int mb;
	/// Mark the macroblock from where min bit rate macroblocks must be encoded if the slice is to be truncated.
	int minMBIndex = len;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPIntra;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Initialisation step: 
	///		lower(D,R) : QP = H264V2_MAX_QP.
	///		upper(D,R) : QP = 1.
	/// Note that the D values represent the worst (max) distortion of only one macroblock in the entire
	/// frame but the R values represent the accumulated (total) rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int mbDmax = 0;
	int	invalidated = 0;
	int	iterations = 0;
	/*
	  /// --------------------- I-Frame Measurement Collection -----------------------------------------------------
	  /// --------------------------------------------------------------------------------------------------
	*/
	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest (max) distortion of all macroblocks.
		Rl += _codec->ProcessIntraMbImplStd(pMb, 1);
		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the macroblock with the peak distortion.
		}//end if _distortion...

	}//end for mb...

  /// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer and assume half required after exiting.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_intraIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (start - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt else do damage control.
	int bitCost = Rl;
	int oldBitCount = Rl;
	if (Rl <= allowedBits)
	{
		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	/// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int goingDown = 1;
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			int model = 0;
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
			{
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);
				model = 1;
			}//end if linear...

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
			{
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.
				model = 2;
			}//end if bisection...

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;

			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// If the previous neighbourhood has not changed and QP is the same as the last encoding of this blk
				/// then it does not have to be re-encoded assuming distortion < Dmax.
				if ((mb >= firstMbChange) || (_pQ[mb] != pMb->_mbEncQP) || (pMb->_distortion[_pQ[mb]] > Dmax))
				{
					/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					pMb->_mbQP = _pQ[mb];
					if (_pQ[mb] > 24)  ///< Assume that below QP = 24 the prediction mode will be the same.
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 0, Dmax, qEnd);
					else
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 1, Dmax, qEnd);
					_pQ[mb] = pMb->_mbQP;

					if (mb < firstMbChange)
						firstMbChange = mb;
				}//end if mb...
				else
					R += pMb->_rate[_pQ[mb]];

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 
			}//end for mb...

	//			for(mb = 0; mb < len; mb++)
	//			{
	//				MacroBlockH264* pMb = &(_codec->_pMb[mb]);
	//				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, 1);
	//				R += pMb->_rate[_pQ[mb]];
	//      }//end for mb...

				/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		/// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _pQ[mb];
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax path Allowed=%d Cost=%d Invalid=%d", allowedBits, R, invalidated);
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax");
		bitCost = R;

	}//end if Rl...
	else ///< For QP = H264V2_MAX_QP the max allowed bits was exceeded and damage control is required.
	{
		///======================================================================================

		/// Sub-optimal Steepest Ascent Algorithm
		bitCost = DamageControl(allowedBits, bitCost);

		if (bitCost >= allowedBits) ///< All failed.
		{
			minMBIndex = _codec->_lumWidth / 16; ///< Hope for the best.
			invalidated = 1;
			for (int mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _codec->_pMb[mb]._mbEncQP;
		}//end if bitCost...

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "I-frame: Damage control path Allowed=%d Cost=%d Iter=%d ListLen=%d ReorderCnt=%d", allowedBits, bitCost, iterations, listLen, cnt);
		//sprintf(_codec->_errorInfo, "I-frame: Damage control");

	}//end else...

	/// Apply the selected quant with the full feedback loop to all macroblocks.
	if (invalidated)
	{
		//  	int bitCount = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// Encode the macroblocks until min null macroblocks.
			if (mb < minMBIndex)
				_codec->ProcessIntraMbImplStd(pMb, 0);
			//  			bitCount += _codec->ProcessIntraMbImplStd(pMb, 1);
			else
				_codec->ProcessIntraMbImplStdMin(pMb);
			//  			bitCount += _codec->ProcessIntraMbImplStdMin(pMb);

		}//end for mb...

  //    bitCost = bitCount;

	}//end if invalidated...

	*bitsUsed = 0;
	//  *bitsUsed = bitCost;
	return(1);
}//end IntraImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm
At max QP for all Mbs the rate limit is exceeded and an alternative quantisation
approach is taken to use the available bits as best as possible. This implementation
zeros more and more of the DCT coeffs until it fits using a sub-optimal Steepest
Ascent Algorithm.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used up to this point.
@return             : The actual bits consumed.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	int i, mb;
	int bitCost = currBitCost;
	int iterations = 0;
	int cnt;

	/// Initialise the ordered mb list.
	int len = _codec->_mbLength;
	int listLen = len;
	for (mb = 0; mb < len; mb++)
		_pMbList[mb] = mb;

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the mbs in increasing distortion.

			/// Exclude completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (_codec->_pMb[mb]._mbEncQP < H264V2_I_MAX_EXT_QP)
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_I_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_I_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 66; break;
					case 66: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 77; break;
					case 77: pMb->_mbQP = 81; break;
					case 81: pMb->_mbQP = 84; break;
					case 84: pMb->_mbQP = 85; break;
					case 85: pMb->_mbQP = 86; break;
					default: pMb->_mbQP = 86; break;
					}///end switch _mbEncQP...

					_codec->ProcessIntraMbImplStd(pMb, 2, 1); ///< Distortion only and without pred mode selection.

				}//end while _distortion[]...

				/// Add back new bits.
				pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
				predR += pMb->_rate[pMb->_mbEncQP];

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessIntraMbImplStd(pMb, 1, 1);
		}//end for mb...

		iterations++;
	}//end while bitCost...

	return(bitCost);
}//end IntraImgPlaneEncoderImplMinMax::DamageControl.

/** Encode the image data for Intra IDR pictures with a mb Dmax limit.
Process all slices and their macroblocks in order. The QP value is decremented
until the mb Dmax is less than the codec _dMax parameter. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the Dxax search is limited to.
	int qEnd = _codec->_minQPIntra;
	int coeffBits = 0;

	if (_codec->_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)
		if ((_codec->_iPictureDMaxMultiplier != 0) || (_codec->_iPictureDMaxMultiplier != 0))
			/// Modify the Dmax value by the I-Picture multiplier and fraction.
			dmax = (dmax * _codec->_iPictureDMaxMultiplier) + ((dmax * _codec->_iPictureDMaxFraction) / 10);

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		/// Descend the QP value until the mb distortion is less than dmax.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessIntraMbImplStd(pMb, 1, 0, dmax, qEnd);
		else
			_codec->ProcessIntraMbImplStd(pMb, 2, 0, dmax, qEnd);
	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplDMax::Encode.

/** Get distortion from an r vs d power model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistPowerModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if ((dl != du) && (rl != ru))
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a power function.
		double beta = -(log((double)rl / (double)ru)) / (log((double)dl / (double)du));
		double alpha = (double)rl / (pow((double)dl, -beta));
		/// Use the power function to predict where r will be. r = alpha.d^(-beta)
		d = (int)exp(-log((double)r / alpha) / beta);
	}//end if dl...

	return(d);
}//end FitDistPowerModel.

/** Get distortion from an r vs d linear model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistLinearModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if (rl != ru)
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a linear function.
		d = (int)((double)((r - rl)*(dl - du)) / (double)(rl - ru)) + dl;
	}//end if dl...

	return(d);
}//end FitDistLinearModel.

/** Get the next quant QP value that has a distortion less than Dmax.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra)
{
	/// 1st iteration required to ensure sync with macroblock dependencies if
	/// it was invalidated or changed since last encoding.
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);

		di = mb._distortion[i];
	}//end if mbIndex...

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if (i < H264V2_MAX_QP)
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
//			int previ = i;
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				//				previ = i;
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmax.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// The delta QP for a mb is constrained to {-26...25}. Therefore if
	/// the current QP value results in a dQP > 25 or < -26 then it must 
	/// be reprocessed before continuing regardless of the Dmax value. The
	/// i not equal to atQ signals that delta QP was out of range.
	int prevQP = GetPrevMbQP(&mb);
	int minQP = prevQP - 26;
	if (minQP < lowestQ) minQP = lowestQ;
	int maxQP = prevQP + 25;
	if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
	if (i < minQP) i = minQP;
	else if (i > maxQP) i = maxQP;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb or delta QP was out of range then
  /// its dependencies have been altered and it must be re-encoded.
	if ((mbIndex >= lclChangeMb) || (i != atQ))
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
			else
				ProcessInterMbImplStd(&mb, 0, 2);         ///< Distortion only.
		}//end if !intra...
		else
			ProcessIntraMbImplStd(&mb, 2, 0); ///< Distortion only.

		di = mb._distortion[i];
	}//end if mbIndex...

	/// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 2);
			else
				ProcessIntraMbImplStd(&mb, 2, 1); ///< Distortion only without pred mode selection.

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

  /// Set the new mb rate at this QP value.
	if (!intra)
	{
		int rate = 0;
		if (!mb._skip)
			rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
		mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.
	}//end if !intra...
	else
		mb._rate[mb._mbEncQP] = MacroBlockLayerBitCounter(&mb);

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer2.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
This method includes extended QP values = {52..71}.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
			{
				if (mb._mbQP > H264V2_MAX_QP)              ///< For extended QP range, temporarily reset for processes below.
					mb._mbQP = H264V2_MAX_QP;

				int rate = 0;
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
				if (!mb._skip)
					rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
				mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.

				mb._mbQP = i;                             ///< Put it back.
			}//end if _mbEncQP...
			else
			{
				ProcessInterMbImplStd(&mb, 0, 1);
			}//end else...

		}//end if !intra...
		else
		{
			ProcessIntraMbImplStd(&mb, 1);
		}//end else...

		di = mb._distortion[i];
	}//end if mbIndex...

  /// The delta QP for a mb is constrained to {-26...25}. Therefore if
  /// the current QP value results in a dQP > 25 or < -26 then it must 
  /// be reprocessed before continuing regardless of the Dmax value.
	int minQP = lowestQ;
	if (i <= H264V2_MAX_QP) ///< Only for the non-extended QP range.
	{
		int prevQP = GetPrevMbQP(&mb);
		minQP = prevQP - 26;
		if (minQP < lowestQ) minQP = lowestQ;
		int maxQP = prevQP + 25;
		if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
		if ((i < minQP) || (i > maxQP))
		{
			if (i < minQP) i = minQP;
			else i = maxQP;
			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];
		}//end if i...
	}//end if i...

	  /// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer3.

/** Get the next quant QP value that has a distortion less than Dmax with approximations.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param epsilon			: The Dmax approximation only has to be within epsilon of Dmax.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra)
{
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded. However, as it will be changed anyway, either up
	/// or down, a short cut approximation is to assume that the previous encoding at the
	/// current QP is approximately correct and the descent/ascent proceeds with these values.
	/// But the mb must be processed at least once before exiting to be valid.
	int atLeastOnce = 0;

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i < H264V2_MAX_QP) && ((Dmax - di) > epsilon))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Re-sync the mb if it was not already processed.
	if ((mbIndex >= lclChangeMb) && (!atLeastOnce))
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);
	}//end if mbIndex...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmaxApprox.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		: Macroblock to operate on.
@param withDR	: With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@return				: Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode and get the prediction. Pred stored in _16x16.
	pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
	if (withDR)
		pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop. The distortion returned includes ROI modification.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...

      /// Region of interest modification.
      mbDistortion = ROIDistortion(pMb->_mbIndex, mbDistortion);
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
  if (withDR)
    pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock with a max distortion criterion.
Code factoring usage. Includes reading the input image, IT, quantisation, vlc encoding and
determining coding patterns, type, etc. _mbQP is decremented until the lum distortion is
below Dmax. If distortion for the given _mbQP is below Dmax then the mb is processed only
once, there is no ascent search. _mbQP must be less than or equal to H264V2_MAX_QP, coeff
zeroing is not implemented in this overload. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined as the starting QP value before this method is called.

  /// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.

  /// Frame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _Lum->Read(c, r);
					if (c)
						prev = _Lum->Read(c - 1, r); ///< Left.
					else
						prev = _Lum->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation --------------------------------------------
	/// Implement the forward and feedback loop into the temp blks. The block coeffs are still 
  /// required for the context-aware vlc coding and therefore the temporary working blocks are
  /// used in the feedback loop. The mb QP will change during the TransAndQuantIntra16x16MBlk() 
  /// method call.
	if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantIntra16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Feedback loop -------------------------------------------------------

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// Distortion with Lum input was calculated in the TransAndQuantIntra16x16MBlk() method. 

	  /// ------------------ Set patterns and type -----------------------------------------------
	  /// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	  /// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
	{
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE) ///< Requires coeff bits without the mb header bits.
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerCoeffBitCounter(pMb);
		else
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);
	}//end if withDR...

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
and ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisation(MacroBlockH264* pMb)
{
	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs of lum and chr are zeroed. {67..69} The AC coeffs of the Chr DC 
	/// 2x2 coeffs additionally zeroed. {70..84} AC coeffs of the Lum DC coeffs additionally 
	/// zeroed. {85} DC coeff of the Chr DC 2x2 coeffs zeroed. {86} DC coeff of the Lum DC 
	/// coeffs zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	int lumDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 69)  ///< Include AC coeff of Chr DC for QP = {67..69}.
	{
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 84)  ///< Include AC coeffs of Lum DC and all AC coeffs of Chr DC for QP = {70..84}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 3; ///< Not the Chr DC term.
		lumDcCoeffZeroed = pMb->_mbEncQP - 69;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 85)  ///< Include all Chr DC coeffs but only AC coeffs of Lum DC for QP = {85}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4; ///< ...and Chr DC term.
		lumDcCoeffZeroed = 15;
	}//end else if _mbEncQP...
	else  ///< All zeroed for QP = {86} and above.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
		lumDcCoeffZeroed = 16;
	}//end else...

	int startPos4x4 = 16 - acCoeffZeroed;
	int startChrDcPos2x2 = 4 - chrDcCoeffZeroed;
	int startLumDcPos4x4 = 16 - lumDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_DC; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_LUM_DC) && (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else if ((blk == MBH264_CB_DC) || (blk == MBH264_CR_DC)) ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startChrDcPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else if blk...
		else ///< if(blk == MBH264_LUM_DC) Lum DC AND zero'ing required.
		{
			if (lumDcCoeffZeroed)
			{
				for (i = startLumDcPos4x4; i < 16; i++)
				{
					if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ4x4[i]] = 0;
				}//end for i...
			}//end if lumDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisation.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
an ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring. Ver 2 optimises the process used
in the original version.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisationVer2(MacroBlockH264* pMb)
{
	//////////////////////////////////////////////////////////////////////////
	  // if(pMb->_mbEncQP <= H264V2_MAX_QP + 15) return; ///< Why are we here?
	//////////////////////////////////////////////////////////////////////////

	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71} 
	/// Lum DC coeffs additionally zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 70)  ///< Include Chr DC coeffs for QP = {67..70}.
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
	}//end else...
	int startPos4x4 = 16 - acCoeffZeroed;
	int startPos2x2 = 4 - chrDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude Chr DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else  ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisationVer2.

/** The absolute min bit encoding of a Std Intra macroblock.
Set and measure the encoding for a min bit implementation of the std Intra
macroblock. This only includes DC prediction and all residual DC and AC
coeffs are zero'ed. QP is set to max. Return the bit cost.
@param pMb	: Macroblock to operate on.
@return		  : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStdMin(MacroBlockH264* pMb)
{
	int rate = 0;
	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_mbQP = H264V2_MAX_QP;
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	/// Force the selection to DC Lum prediction for all macroblocks.
	pMb->_intra16x16PredMode = MacroBlockH264::Intra_16x16_DC;
	GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);

	_RefLum->Write16x16(*(_16x16)); ///< Write the prediction into the ref.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);

	pMb->_intraChrPredMode = MacroBlockH264::Intra_Chr_DC;
	GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
	GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);

	_RefCb->Write8x8(*(_8x8_0));
	_RefCr->Write8x8(*(_8x8_1));

	/// Clear all mb coeffs for encoding. Implies all difference DC and AC coeffs are zero.
	for (int blk = 0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		(pBlk->GetBlkOverlay())->Clear();
		pBlk->SetNumCoeffs(0);
	}//end for blk...

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. For Intra slices
	/// no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;
	if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	///< Previous macroblock within same slice.
			pMb->_mb_qp_delta = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate --------------------------------------------------------
	rate = MacroBlockLayerBitCounter(pMb);

	return(rate);
}//end ProcessIntraMbImplStdMin.

/** Encode the image data for Inter pictures.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Create an img to capture the difference between the input img 
  /// and the motion comp pred img. The collection is done per mb and dumped to file after.
  //int selectedFrameNum = 0;
  ////int selectedFrameList[15] = {19, 78, 93, 148, 152, 154, 156, 173, 182, 194, 204, 207, 213, 216, 221}; ///< Foreman
  ////int selectedFrameList[7] = {24, 62, 126, 184, 210, 258, 278}; ///< Mobile
  //int selectedFrameList[9] = {15, 24, 52, 114, 124, 152, 226, 256, 288}; ///< Soccer
  //for(int i = 0; i < 9; i++)
  //{
  //  if(_codec->_frameNum == selectedFrameList[i])
  //    selectedFrameNum = _codec->_frameNum;
  //}//end for i...

  //short* pDiffLum = NULL;
  //short* pDiffCb  = NULL;
  //short* pDiffCr  = NULL;
  //OverlayMem2Dv2* diffLum	= NULL;
  //OverlayMem2Dv2* diffCb	= NULL;
  //OverlayMem2Dv2* diffCr	= NULL;

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  pDiffLum = new short[(_codec->_lumWidth * _codec->_lumHeight) + 2*(_codec->_chrWidth * _codec->_chrHeight)];
  //  pDiffCb = &(pDiffLum[_codec->_lumWidth * _codec->_lumHeight]);
  //  pDiffCr = &(pDiffLum[(_codec->_lumWidth * _codec->_lumHeight) + (_codec->_chrWidth * _codec->_chrHeight)]);

	 // diffLum	= new OverlayMem2Dv2(pDiffLum, _codec->_lumWidth, _codec->_lumHeight, _codec->_lumWidth, _codec->_lumHeight);
	 // diffCb	= new OverlayMem2Dv2(pDiffCb, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);
	 // diffCr	= new OverlayMem2Dv2(pDiffCr, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);

  //  /// Copy the input img into the diff img from where the comp pred img will be subtracted.
  //  _codec->_Lum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  _codec->_Cb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Cr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Lum->SetOrigin(0, 0);
  //  _codec->_Cb->SetOrigin(0, 0);
  //  _codec->_Cr->SetOrigin(0, 0);

  //  diffLum->Write(*_codec->_Lum);
  //  diffCb->Write(*_codec->_Cb);
  //  diffCr->Write(*_codec->_Cr);

  //  /// Restore blk dimensions.
  //  diffLum->SetOverlayDim(16, 16);
  //  diffCb->SetOverlayDim(8, 8);
  //  diffCr->SetOverlayDim(8, 8);
  //  _codec->_Lum->SetOverlayDim(4, 4);
  //  _codec->_Cb->SetOverlayDim(4, 4);
  //  _codec->_Cr->SetOverlayDim(4, 4);
  //}//end if _frameNum...
  /////////////////////////////////////////////////////////////////////////////////////////////

	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		/////////////////////////////////////////////////////////////////////////////////////////////
		/// Research Data Collection: Mb data capture.
		//if(_codec->_frameNum == selectedFrameNum)
		//{
		   // diffLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // diffCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // diffCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  _codec->_RefLum->SetOverlayDim(16, 16);
		//  _codec->_RefCb->SetOverlayDim(8, 8);
		//  _codec->_RefCr->SetOverlayDim(8, 8);
		   // _codec->_RefLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // _codec->_RefCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // _codec->_RefCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  diffLum->Sub(*_codec->_RefLum);
		//  diffCb->Sub(*_codec->_RefCb);
		//  diffCr->Sub(*_codec->_RefCr);

		//  _codec->_RefLum->SetOverlayDim(4, 4);
		//  _codec->_RefCb->SetOverlayDim(4, 4);
		//  _codec->_RefCr->SetOverlayDim(4, 4);
		//}//end if _frameNum...
		/////////////////////////////////////////////////////////////////////////////////////////////

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this macroblock as the median of the neighbourhood 
		/// vectors and subtract it from the macroblock vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
		pMb->_mbQP = _codec->_slice._qp;
		_codec->ProcessInterMbImplStd(pMb, addRef, 0);

	}//end for mb...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Dump to file and clean up in reverse order.

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  char* filenameBase = "c:/keithf/Videos/StdTestVideos/Soccer352x288_30fps";
  //  char  sQP[8];
  //  char  sFrmNum[16];
  //  char sFilename[512];
  //  char sFilenameFinal[512];

  //  strcpy(sFilename, (const char*)filenameBase);
  //  strcat(sFilename, (const char*)"_qp");
  //  strcat(sFilename, (const char*)(_itoa(_codec->_slice._qp, sQP, 10)));
  //  strcat(sFilename, (const char*)"_frm");
  //  strcat(sFilename, (const char*)(_itoa(selectedFrameNum, sFrmNum, 10)));

  //  diffLum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  diffLum->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_lum.csv");
  //  diffLum->Dump(diffLum, sFilenameFinal, "");

  //  diffCb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCb->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cb.csv");
  //  diffLum->Dump(diffCb, sFilenameFinal, "");

  //  diffCr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCr->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cr.csv");
  //  diffLum->Dump(diffCr, sFilenameFinal, "");
  //}//end if _frameNum...

  //if(diffCr != NULL)
  //  delete diffCr;
  //if(diffCb != NULL)
  //  delete diffCb;
  //if(diffLum != NULL)
  //  delete diffLum;

  //if(pDiffLum != NULL)
  //  delete[] pDiffLum;
  /////////////////////////////////////////////////////////////////////////////////////////////

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplStdVer1::Encode.

/** The forward and inverse loop of a Std Inter macroblock.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

	/// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------------
	if (pMb->_mbEncQP > H264V2_MAX_QP)
		CoeffZeroingQuantisationVer2(pMb);
	/*
	  {
		int blk, i;
		const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
		const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

		/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
		/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that
		/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71}
		/// Lum DC coeffs additionally zeroed.
		int acCoeffZeroed     = 15; ///< By default.
		int chrDcCoeffZeroed  = 0;
		if( pMb->_mbEncQP <= (H264V2_MAX_QP + 15) )
		  acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
		else if( pMb->_mbEncQP <= 70 )  ///< Include Chr DC coeffs for QP = {67..70}.
		{
		  chrDcCoeffZeroed = pMb->_mbEncQP - 66;
		}//end else if _mbEncQP...
		else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
		{
		  acCoeffZeroed     = 16;
		  chrDcCoeffZeroed  = 4;
		}//end else...
		int startPos4x4 = 16 - acCoeffZeroed;
		int startPos2x2 = 4 - chrDcCoeffZeroed;

		/// Zero coeff in the mb according to the QP rules above.
		  for(blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
		  {
			  BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		  short* pB = pBlk->GetBlk();

		  if( (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC) )  ///< Exclude Chr DC blks.
		  {
			for(i = startPos4x4; i < 16; i++)
			{
			  if( pB[pZZ4x4[i]] )  ///< Only need to change coeffs that are not already zero.
				pB[pZZ4x4[i]] = 0;
			}//end for i...
		  }//end if blk...
		  else  ///< Chr DC blks AND zero'ing required.
		  {
			if(chrDcCoeffZeroed)
			{
			  for(i = startPos2x2; i < 4; i++)
			  {
				if( pB[pZZ2x2[i]] )  ///< Only need to change coeffs that are not already zero.
				  pB[pZZ2x2[i]] = 0;
			  }//end for i...
			}//end if chrDcCoeffZeroed...
		  }//end else...

		  }//end for blk...

	  }//end if _mbEncQP...
	*/
	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			InverseTransAndQuantInter16x16MBlk(pMb, 1);

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));            ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the Distortion & Rate and store results ----------------------------------
	/// Store distortion for this quant value.
	if (withDR)
	{
		/// Calc distortion with Input. If there was a coded blk pattern then compare with temp img else
	  /// with the unaltered ref img.
		OverlayMem2Dv2* pLI = _RefLum;
		OverlayMem2Dv2* pCbI = _RefCb;
		OverlayMem2Dv2* pCrI = _RefCr;
		if (pMb->_coded_blk_pattern)
		{
			pLI = _16x16;
			pCbI = _8x8_0;
			pCrI = _8x8_1;
		}//end else if _coded_blk_pattern...

#ifdef USE_ABSOLUTE_DIFFERENCE
		distortion += pLI->Tad16x16(*_Lum);	///< Total abs distortion between Ref and input Lum.
		distortion += pCbI->Tad8x8(*_Cb);
		distortion += pCrI->Tad8x8(*_Cr);
#else
		distortion += pLI->Tsd16x16(*_Lum);	///< Total square distortion between Ref and input Lum.
		distortion += pCbI->Tsd8x8(*_Cb);
		distortion += pCrI->Tsd8x8(*_Cr);
#endif
    /// Modify the distortion with the region of interest map.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);
		pMb->_distortion[pMb->_mbEncQP] = distortion;

		//    if(!pMb->_skip)
		//		  rate = MacroBlockLayerBitCounter(pMb);
		//    else
		if (pMb->_skip)
		{
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (int i = 1; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _skip...

	//    pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	/// Store rate for this quant value if required.
	if ((withDR == 1) && (!pMb->_skip)) ///< For withDR = 2, no rate calculation is done.
	{
		rate = MacroBlockLayerBitCounter(pMb);
		pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	return(rate);
}//end ProcessInterMbImplStd.

/** The forward and inverse loop of a Std Inter macroblock with a Dmax criterion.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Includes accumulation of the frame MAD measure.
Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	/// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

  /// Fame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _16x16->Read(c, r);
					if (c)
						prev = _16x16->Read(c - 1, r); ///< Left.
					else
						prev = _16x16->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
  /// Includes the distortion calc and the inverse quant and transform to the temp blks. For 
  /// extended range QP > H264V2_MAX_QP the appropriate coeffs are zeroed. 
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantInter16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
	/// The inverse to the temp blks was included in the TransAndQuantInter16x16MBlk() method above.

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));  ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the rate and store results ----------------------------------
	if (withDR && pMb->_skip)
	{
		/// Ensure coeffs settings are synchronised for future use by mb neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end if withDR...

	/// Store rate for this quant value if required.
	if (!pMb->_skip)
	{
		if ((withDR == 1) || (withDR == 3)) ///< For withDR = 2, no rate calculation is done.
		{
			rate = MacroBlockLayerCoeffBitCounter(pMb);
			pMb->_rate[pMb->_mbEncQP] = rate;
		}//end if withDR...
	}//end if !skip...

	return(rate);
}//end ProcessInterMbImplStd.

/// Does NOT include motion prediction and compensation. Assumes these mb members are already set before called.
int H264v2Codec::ProcessInterMbImplStdMin(MacroBlockH264* pMb)
{
	/// Set the difference to the compensated reference to zero and therefore no operation needs to be
	/// performed on the ref. Zero and clear all blocks.

	  /// NB: _mbQP must be correctly defined before this method is called.
	int rate = 0;

	/// Base settings for all inter macroblocks.
	pMb->_intraFlag = 0;
	pMb->_skip = 0;

	/// Clear the delta quantisation parameter and set the _mbQP to the same as the previous non-skipped mb. The
  /// _mbQP does not have any impact because all coeffs are set to zero.
	pMb->_mb_qp_delta = 0;
	/// Find the previous non-skipped macroblock.
	int prevMbIdx = pMb->_mbIndex - 1;
	/// Re-align the quantisation param for future delta qp calculations.
	if (prevMbIdx >= 0)
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
			pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mbQP = _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mbQP = _slice._qp;

	/// Force all values to zero before encoding.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);
	_16x16->Clear();
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_0->Clear();
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);
	_8x8_1->Clear();

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode. If motion is zero then mb is skipped.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	if (!pMb->_skip)
		rate = MacroBlockLayerBitCounter(pMb);
	else
	{
		/// Ensure coeffs settings are synchronised for future use by neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end else...

	pMb->_rate[0] = rate;

	return(rate);
}//end ProcessInterMbImplStdMin.

/** Calc delta QP based on macroblock QP.
The coded block pattern, _intraFlag and _mbQP values must be correctly set before calling this
method. The _skip mode for P mbs alters the _mbQP value.
@param pMb    : Macroblock to operate on.
@return       : Delta QP for these mb parameters.
*/
int H264v2Codec::GetDeltaQP(MacroBlockH264* pMb)
{
	int deltaQP = 0;

	/// Find the previous non-skipped macroblock. For Intra slices no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;

	if (pMb->_coded_blk_pattern || pMb->_intraFlag)
	{
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				deltaQP = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
			else
				deltaQP = pMb->_mbQP - _slice._qp;
		}//end if prevMbIdx...
		else
			deltaQP = pMb->_mbQP - _slice._qp;
	}//end if _coded_blk_pattern...
	else
	{
		/// Re-align the quantisation param for future delta qp calculations.
		if (prevMbIdx >= 0)
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
			else
				pMb->_mbQP = _slice._qp;
		}//end if prevMbIdx...
		else
			pMb->_mbQP = _slice._qp;
	}//end else...

	return(deltaQP);
}//end GetDeltaQP.

/** Get the previous macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Previous Mb QP.
*/
int H264v2Codec::GetPrevMbQP(MacroBlockH264* pMb)
{
	int prevMbIdx = pMb->_mbIndex - 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((prevMbIdx >= 0) && (pMb->_slice == _pMb[prevMbIdx]._slice))
		return(_pMb[prevMbIdx]._mbQP);
	else
		return(_slice._qp);
}//end GetPrevMbQP.


/** Get the next macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Next Mb QP.
*/
int H264v2Codec::GetNextMbQP(MacroBlockH264* pMb)
{
	int nextMbIdx = pMb->_mbIndex + 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((nextMbIdx < _mbLength) && (pMb->_slice == _pMb[nextMbIdx]._slice))
		return(_pMb[nextMbIdx]._mbQP);
	else
		return(pMb->_mbIndex);
}//end GetPrevMbQP.

/** Encode the image data for Inter pictures with QP adaptation at macroblock level.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 + X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
The macroblock wide _mbPQ is adapted to ensure that the resulting stream will use
no more than allowedBits. This algorithm uses a bisection technique to minimise the
max distortion by adapting the macroblock quant value until the nearest rate to the
total allowable bits is achieved.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb, bitCount;
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int minMBIndex = len; ///< Mark the macroblock from where min units must be encoded.

	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

  /// Mark this time point for later use.
	int preMotionTime = 0;
	if (_codec->_timeLimitMs)
		preMotionTime = (int)_codec->GetCounter();

	///	---------------------- Motion Vector encoding ---------------------------------------

	/// In this implementation QP adaptation is performed after full motion compensation.
	/// Get the motion vector list to work with. Assume SIMPLE2D type list.
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

	/// Prepare the compensation on a per macroblock basis.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Count the bits used for the motion vectors by iterating through the
	/// macroblocks and encoding the differential motion vector diff (_mvdX,_mvdY). 
  /// Check that there are sufficient bits available for each vector. If not then 
  /// truncate the estimation result and mark all remaining macroblocks as skipped. 
  /// Store the bit cost of the mb with only motion vectors coded in _rate[0].
	int bitCost = 0;
	int mbSkipRun = 0;
	/// Start with all mbs skipped to the end by counting bits for mbSkipRun = len;
	int minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(len);
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Set the mb with the the motion vector, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors and subtract from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		/// Motion compensate the macroblock.
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		int lclAllowedBits = (allowedBits - bitCost) - minPictureBitsToEnd;	///< So far before encoding this MVD pair.

	  /// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);

		/// For skipped mbs, the previous skipped bit count must be included in the minPictureBitsToEnd.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			lclBitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Are there enough bits left to encode this run + MVD pair?
			if (lclBitCost < lclAllowedBits)
				bitCost += lclBitCost;  ///< Update the accumulator.
			else	///< Truncation condition.
			{
				/// Clean up all remaining macroblocks as skipped and exit. In this implementation
				/// when there are not enough bits to encode all the motion vectors the estimated list
				/// is truncated with [0,0] difference vectors or [0,0] motion with special conditions 
			  /// and re-compensated.
				return(DamageControlMvOnly(allowedBits, bitsUsed));
			}//end else...

			mbSkipRun = 0; ///< Reset.

		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;

		/// Update remaining bits for next mb where all remaining mbs are skipped.
		int mbSkippedToEnd = mbSkipRun + ((len - 1) - mb);
		if (mbSkippedToEnd)
			minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkippedToEnd);
		else
			minPictureBitsToEnd = 0;
	}//end for mb...
  /// Include the last run to the end.
	bitCost += minPictureBitsToEnd;
	if (bitCost >= allowedBits)  ///< ...and check.
		return(DamageControlMvOnly(allowedBits, bitsUsed));
	int minMvBitsToEnd = bitCost;	///< Hold the total motion vector with zero residual bit cost.

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock Q search.
	-------------------------------------------------------------------------------------------
	*/
	/// Initialisation step: 
	  ///		lower(D,R) : QP = H264V2_MAX_QP.
	  /// Note that the D values represent the worst distortion of only one macroblock in the entire
	  /// frame but the R values represent the accumulated rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int iterations = 0;
	int	invalidated = 0;
	int mbDmax = 0;

	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
	  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
		Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		if (!pMb->_skip)
		{
			/// Sum of skip run and coded mb bits accumulated.
			Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the mb index with the peak distortion.
		}//end if _distortion...

		/// No early exit because damage control uses this result = Rl.

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer but exclude the motion estimation time
  /// as an offset.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_interIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (preMotionTime - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt from quant param = H264V2_MAX_QP, else do damage control.
	if (Rl <= allowedBits)
	{

		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	  /// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;
			mbSkipRun = 0;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, false);
				R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
				if (!pMb->_skip)
				{
					/// Sum of skip run and coded mb bits accumulated.
					R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
					mbSkipRun = 0;
				}//end if !_skip...
				else
					mbSkipRun++;

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 

			}//end for mb...
	    /// Add last skip run.
			if (mbSkipRun)
				R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		    /// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
			{
				_codec->_pMb[mb]._mbQP = _pQ[mb];
				_codec->_pMb[mb]._mbEncQP = _pQ[mb];
			}//end for mb...
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "P-frame: all good Allowed=%d Cost=%d", allowedBits, R);

	}//end if Rl...
	else	///< Damage control.
	{
		bitCost = DamageControl(allowedBits, Rl);

		if (bitCost >= allowedBits) ///< All failed.
			minMBIndex = 0;

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "P-frame: damage control Allowed=%d Cost=%d", allowedBits, bitCost);

	}//end else Damage control...

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock final encoding.
	-------------------------------------------------------------------------------------------
	*/
	/// Rip through each macroblock as a linear array and process each block within the macroblock.
	/// The _mbEncPQ values have been set in the above encoding.
	mbSkipRun = 0;
	bitCount = 0;
	for (int mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// Encode the mbs and add to Ref img until min null mb position.
		if (mb < minMBIndex)
		{
			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
	  //      bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 0);
			bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 1);
		}//end if mb...
		else
			bitCount += _codec->ProcessInterMbImplStdMin(pMb);
		if (!pMb->_skip)
		{
			bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	*bitsUsed = 0;
	int ret = 1;
	if (bitCount > allowedBits)  ///< Failed to meet bit target.
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bit target unattainable";
		ret = 0;
	}//end if bitCount...

	return(ret);
}//end InterImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm for motion vectors only condition.
Clean up all remaining macroblocks as skipped and exit. In this implementation
when there are not enough bits to encode all the motion vectors the estimated list
is truncated with [0,0] difference vectors or [0,0] motion with special conditions
and re-compensated.
@param allowedBits  : Bits to use.
@param bitsUsed     : Bits consumed on the stream.
@return             : 1 = success, 0 = failed.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControlMvOnly(int allowedBits, int* bitsUsed)
{
	int mb;
	/// Stage 1: Start by taking a snapshot of improvement (mostly negative) in distortion between
	/// the current estimated mv and the predicted mv per mb. Count the total bit rate to determine
	/// how far off from the allwedBits these mvs are.
	int len = _codec->_mbLength;
	int bitCost = 0;
	int mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
		pMb->_include = 1;  ///< Default.

		/// Set the mb with the the mv, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		int topLeftX = pMb->_offLumX;
		int topLeftY = pMb->_offLumY;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

		/// Compensate with the pred mv and measure the mb distortion.
		_codec->_pMotionCompensator->Invalidate();
		_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, predX, predY);
		int distortion = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);

		if ((mvx != predX) || (mvy != predY))  ///< Only if the estimated mv and the pred mv are not already equal.
		{
			_codec->_pMotionCompensator->Invalidate();
			_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, mvx, mvy);
			pMb->_distortion[0] = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);
		}//end if mvx...
		else
		{
			/// Estimated mv is equal to pred mv.
			pMb->_distortion[0] = distortion;
			pMb->_include = 0;
		}//end else...

		/// Expected increase in distortion by choosing the pred mv.
		_pDistortionDiff[mb] = distortion - pMb->_distortion[0];

		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Set the mv difference before processing the mb.
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
		/// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);
		/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			bitCost += (lclBitCost + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
			mbSkipRun = 0; ///< Reset.
		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;
	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Stage 2: Sub optimal solution proceeds by scanning the next mb with the initial least distortion 
	/// impact after replacing the estimated mv with the pred mv. Continue to replace the mv with the 
	/// pred mv until the accumulated bits are approximately below the allowed bits ignoring the skip run
	/// bit run contribution. Rely on the initial _rate[0] calculation above to guess the rate savings. 
	/// Then re-calculate actual bits at the end to determine whether or not the loop must continue.
	int forceStop = 0;
	while ((bitCost > allowedBits) && !forceStop)
	{
		///--------------------------------------------------------------------------------------
		int bitSavingRequired = bitCost - allowedBits;
		int savedBits = 0;
		while ((savedBits < bitSavingRequired) && !forceStop)
		{
			int currentLowestDistDiff = 0x7FFFFFFF; ///< Very large starting point.
			/// Find the next lowest distortion difference.
			int nextMb = -1;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
				if (pMb->_include && (_pDistortionDiff[mb] < currentLowestDistDiff))
				{
					currentLowestDistDiff = _pDistortionDiff[mb];
					nextMb = mb;
				}//end if _include...
			}//end for mb...

			if (nextMb >= 0) ///< A candidate mb was found.
			{
				/// Approximate the saving by the existing rate[0] value by assuming that
				/// this mb will be skipped. Ignore the savings on the improved skip run.
				savedBits += _codec->_pMb[nextMb]._rate[0];
				/// Exclude from further checks.
				_codec->_pMb[nextMb]._include = 0;
			}//end if nextMb...
			else
				forceStop = 1;

		}//end while savedBits...

		///--------------------------------------------------------------------------------------
		/// Re-process each mb and accumulate the bit cost. All mbs that are not included must
		/// be set to the pred mv. Only those mbs where the mv has changed are re-compensated.
		bitCost = 0;
		mbSkipRun = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// The pred mv may now be different.
			int predX, predY;
			MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

			if (!pMb->_include)  ///< Marked as a previously predicted mv and mv was set to pred mv.
			{
				/// Set the result mv list to the pred mv.
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 0, predX);
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 1, predY);

				/// Check that this mv is the pred mv.
				if ((pMb->_mvX[MacroBlockH264::_16x16] != predX) || (pMb->_mvY[MacroBlockH264::_16x16] != predY))
				{
					/// Re-compensate if it has changed.
					_codec->_pMotionCompensator->Invalidate();
					_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, predX, predY);
				}//end if _mvX...

			}//end if !include...

			/// Store the motion vector and pred mv in the mb.
			int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
			int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
			pMb->_mvX[MacroBlockH264::_16x16] = mvx;
			pMb->_mvY[MacroBlockH264::_16x16] = mvy;
			pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
			pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
			int r = _codec->ProcessInterMbImplStdMin(pMb);
			/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
			if (!pMb->_skip)
			{
				/// Sum the run and coding bit contributions.
				bitCost += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
				mbSkipRun = 0; ///< Restart
			}//end if !_skip...
			else  ///< Skipped.
				mbSkipRun++;

		}//end for mb...

		/// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	}//end while bitCost...

	/// Check that a solution is possible.
	if (forceStop)
	{
		*bitsUsed = 0;
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Forced stop - no solution possible";
		return(0); ///< Failed.
	}//end if allowedBits...

	  /// ...and then exit.
	int ret = 1;
	if (bitCost > allowedBits)
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bits exceeded in trucation";
		ret = 0;
	}//end if bitCost...

	*bitsUsed = 0;
	return(ret); ///< Something is coded so it is considered successful.
}//end InterImgPlaneEncoderImplMinMax::DamageControlMvOnly.

/** Damage control algorithm
Their are insufficient bits at the max QP and alternative quantisation approaches are required.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used so far for the last encoding of mv and max QP
@return             : Bit cost of this implementation.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	///======================================================================================

	/// Sub-optimal Steepest Ascent Algorithm

	int i, mb;
	int len = _codec->_mbLength;
	int bitCost = currBitCost;
	int iterations = 0;

	/// Initialise the ordered mb list where skipped mbs will never become unskipped and can therefore be excluded.
	int listLen = 0;
	for (mb = 0; mb < len; mb++)
	{
		if (!_codec->_pMb[mb]._skip)
			_pMbList[listLen++] = mb;
	}//end for mb...

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the non-skipped mbs in increasing distortion.

			/// Only included newly skipped and completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (!_codec->_pMb[mb]._skip && (_codec->_pMb[mb]._mbEncQP < H264V2_MAX_EXT_QP))
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			int cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 55; break;
					case 55: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 70; break;
					case 70: pMb->_mbQP = 71; break;
					default: pMb->_mbQP = 71; break;
					}///end switch _mbEncQP...

					_codec->ProcessInterMbImplStd(pMb, 0, 2);

				}//end while _distortion[]...

				/// Add back new bits.
				if (!pMb->_skip)
				{
					pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
					predR += pMb->_rate[pMb->_mbEncQP];
				}//end if !_skip ...

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		int mbSkipRun = 0;
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
			if (!pMb->_skip)
			{
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				mbSkipRun = 0;
			}//end if !_skip...
			else
				mbSkipRun++;

		}//end for mb...
	  /// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		iterations++;
	}//end while bitCost...

	return(bitCost);

	//    if(bitCost >= allowedBits) ///< All failed.
	//		  minMBIndex = 0;

		///======================================================================================
		/*
		/// Sub-optimal Steepest Descent Algorithm

		/// QP = H264V2_MAX_QP for all mbs still uses too many bits so the extended range of QP = {51..71} is
		/// used here to find a near optimal solution.
		int i;
		bitCost = 0;

		/// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		/// Initialise the ordered mb list.
		int listLen = 0;
		mbSkipRun = 0;
		  for(mb = 0; mb < len; mb++)
		  {
		  MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		  _pMbList[listLen++] = mb; ///< Arbitrary order for the mb list.

		  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			  pMb->_mbQP = H264V2_MAX_EXT_QP;

			  /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			  bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		  if(!pMb->_skip)
		  {
			/// Sum of skip run and coded mb bits accumulated.
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		  }//end if !_skip...
		  else
			mbSkipRun++;

			  /// Early exit if this min point is still not possible.
			  if(bitCost >= allowedBits)
				  break;

		  }//end for mb...
		/// Add last skip run.
		if(mbSkipRun)
		  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		R = 0;
		iterations  = 0;

			/// Only proceed if there is hope.
			if(bitCost < allowedBits)
		{
		  /// Starting from highest distortion and lowest rate, slowly decrease the distortion
		  /// and count the approx bit improvement until a good guess is acheived. Then test the
		  /// guess for the actual improvement. Reverse up the audit trail until it fits.

		  /// Audit trail initialisation. -1 indicates no entry.
		  memset(_pLastMbCoded, 0xFF, len * sizeof(int));
		  int lastMbPos = 0;

		  /// Repeat until the solution converges but limit it to 3 iterations for speed.
		  int prevBitCost = 0;
		  while( (bitCost > prevBitCost) && (iterations < 3) )
		  {
			prevBitCost = bitCost;
			int predR = bitCost;
			/// Make a guess by iteratively adjusting predicted rate predR
			while( (listLen > 1)&&(predR < allowedBits) )
			{
			  /// Step 2: Order the mbs in decreasing distortion.

			  /// Included all mbs from the old list except for those that have decreased down
			  /// to QP = {51}.
			  int currListLen = listLen;
			  listLen = 0;
			  for(i = 0; i < currListLen; i++)
			  {
				mb = _pMbList[i];
				if(_codec->_pMb[mb]._mbEncQP > H264V2_MAX_QP)
				  _pMbList[listLen++] = mb;
			  }//end for mb...

			  /// Bubble sort list in descending order of distortion.
			  int cnt = len;
			  while(cnt)
			  {
				cnt = 0; ///< Count how many re-orderings occur.
				for(i = 1; i < listLen; i++)
				{
				  MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i-1]]);
				  MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
				  if( pMb2->_distortion[pMb2->_mbEncQP] > pMb1->_distortion[pMb1->_mbEncQP] )
				  {
					/// Swap places.
					int tmp       = _pMbList[i-1];
					_pMbList[i-1] = _pMbList[i];
					_pMbList[i]   = tmp;
					cnt++;
				  }//end if _distortion...
				}//end for i...
			  }//end while cnt...

			  /// Step 3: Decrease the distortion of mb at the head of the ordered list to just less than the
			  /// next one in the list.
			  int mb1 = _pMbList[0]; /// Head of ordered list.
			  int mb2 = _pMbList[1]; /// Next in ordered list.
			  int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			  int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			  /// For the unusual case where the listLen == 1, set them to the same.
			  if(listLen == 1)
				d2 = d1;

			  MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

			  /// Store the current mb encoding in the audit trail lists.
			  _pLastMbCoded[lastMbPos]  = mb1;
			  _pLastMbQP[lastMbPos++]   = pMb->_mbEncQP;
			  if(lastMbPos >= len) ///< Loop around.
				lastMbPos = 0;

			  R = pMb->_rate[pMb->_mbEncQP];  ///< Remember R at this point in case the loop below does not execute.
			  predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
			  while( (pMb->_distortion[pMb->_mbEncQP] >= d2) && (pMb->_mbEncQP > H264V2_MAX_QP) && ((predR+R) <= allowedBits) )
			  {
				/// Select new QP and process.
				pMb->_mbQP = NextQPDec[pMb->_mbEncQP];
				  R = _codec->ProcessInterMbImplStd(pMb, 0, 1);
			  }//end while _distortion[]...

			  /// Add back new bits.
			  predR += R;

			}//end while listLen...

			/// Step 3: Test the new solution. On exit of the above loop, the approx
			/// bit rate is just too high and therefore the audit trail is used to reverse
			/// until it fits.

			if(lastMbPos != 0)  ///< Back up by 1.
			  lastMbPos--;
			else ///< Wrap around.
			  lastMbPos = len - 1;

			bitCost = predR;  ///< Start with the guess made above.

			while( (bitCost >= allowedBits) && (_pLastMbCoded[lastMbPos] != -1) )
			{
			  _codec->_pMb[_pLastMbCoded[lastMbPos]]._mbEncQP = _pLastMbQP[lastMbPos];
			  _pLastMbCoded[lastMbPos] = -1;  ///< Mark as used goods.
			  if(lastMbPos != 0)  ///< Back up by 1.
				lastMbPos--;
			  else ///< Wrap around.
				lastMbPos = len - 1;

			  mbSkipRun = 0;
				bitCost = 0;
				for(int mb = 0; mb < len; mb++)
				{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
				bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
				if(!pMb->_skip)
				{
				  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				  mbSkipRun = 0;
				}//end if !_skip...
				else
				  mbSkipRun++;

				}//end for mb...
			  /// Add last skip run.
			  if(mbSkipRun)
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			}//end while bitCost...

			iterations++;
		  }//end while bitCost...

		}//end if bitCost...
		else ///< All failed so mark all for min encodings and hope for the best.
		{
			  minMBIndex = 0;
		}//end else...
		*/
		///======================================================================================
		 /*
		 /// Alternating Bi-Section Algorithm.

		 Ru = Rl;  ///< Upper is now QP = {51} determined above.
		 Du = Dl;
		 Rl = 0;
		 Dl = 0;
		 mbDmax = 0;
		 qEnd   = H264V2_MAX_QP;

		 /// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		 mbSkipRun = 0;
		   for(mb = 0; mb < len; mb++)
		   {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			   pMb->_mbQP	  = H264V2_MAX_EXT_QP;
			   /// Include all macroblocks at the start.
			   pMb->_include = 1;
			   _pQl[mb]      = H264V2_MAX_EXT_QP;
			   _pQ[mb]	      = H264V2_MAX_EXT_QP;	///< Active quantiser vector is always the lower (max distortion) side.

			   /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		   /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			   Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			   if(pMb->_distortion[H264V2_MAX_EXT_QP] > Dl)
			   {
				   Dl = pMb->_distortion[H264V2_MAX_EXT_QP];
				   mbDmax = mb;	///< Mark the mb index with the peak distortion.
			   }//end if _distortion...

			   /// Early exit if this min point is still not possible. Mark all as min encodings and hope it fits.
			   if(Rl > allowedBits)
		   {
				   minMBIndex = 0;
				   break;
		   }//end if Rl...

		   }//end for mb...
		 /// Add last skip run.
		 if(mbSkipRun)
		   Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		 /// Step 2: Proceed with optimisation algorithm with QP = {51..71}
		 if(Rl < allowedBits)
		 {
			   /// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
			   /// Adjust the available bits to be epsilon below allowedBits.
			   int closeEnough = allowedBits/250;	///< 0.4%
			   if(closeEnough < 16)
				   closeEnough = 16;
			   int closeEnoughDist = 8;	///< Sqr error per macroblock.

		   /// Model based faster algorithm to improve on the bi-section method.

			   /// Modify the target rate to a close offset on the low rate side.
			   int bitTarget = allowedBits - closeEnough;

			   /// Initialisation is complete and the adapting bi-section/power model algorithm starts
			   /// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
			   /// or 2) small change in distortion when reducing the interval.
			   int done = 0;
			   while(!done)
			   {
				   int prevDmax = Dmax;

				   /// Make a prediction assuming a power law model.
	   //			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
				   /// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
	   //			if( (Dmax < Du)||(Dmax > Dl) )	///< Out of bound.
	   //				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

				   /// Encourage the descent direction by adding a decreasing factor to the
				   /// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
	   //		  Dmax += abs(Dl - Dmax)/4;

	   //			if( (Dmax < Du)||(Dmax > Dl)||(Dmax == prevDmax) )	///< Still out of bound.
					   Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

				   /// At each macroblock reduce the quant value until the distortion is lower
				   /// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector
				   /// as the previous best choice.
				   R = 0;
				   int firstMbChange = len;
				   if(invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
					   firstMbChange = 0;
			 mbSkipRun = 0;
				   for(mb = 0; mb < len; mb++)
				   {
					   MacroBlockH264* pMb = &(_codec->_pMb[mb]);

					   /// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					   _pQ[mb] = _codec->GetMbQPBelowDmaxVer3(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, FALSE);
					   R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
			   if(!pMb->_skip)
			   {
				 /// Sum of skip run and coded mb bits accumulated.
				 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				 mbSkipRun = 0;
			   }//end if !_skip...
			   else
				 mbSkipRun++;

					   /// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points
					   /// for the whole frame.

				   }//end for mb...
			 /// Add last skip run.
			 if(mbSkipRun)
			   R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

				   /// Test the stopping criteria.
				   int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
				   int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
				   int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
				   if( (rBndDiff < (4*closeEnough)) ||
						   ( (rDiff < closeEnough)||((dDiff < closeEnoughDist))) ||
				 (iterations > _codec->_interIterations) )
				 {
					   /// The new point is the preferable point to choose but if the rate is not below allowedBits
					   /// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs
			   /// must be re-processed.
					   if(R > allowedBits)
					   {
						   /// Load the lower vector as it is always below the target rate.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   R = Rl;
				 invalidated = 1;
					   }//end if R...
			   else
				 invalidated = 0;

					   /// Optimal solution is found.
					   done = 1;
				   }//end if rDiff...
				   else
				   {
					   if(allowedBits > R)	///< Inner predicted point is now lower point.
					   {
						   Dl	= Dmax;
						   Rl	= R;
						   /// pQ[] is the lower vector.
						   memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
						   invalidated = 0;
					   }//end if allowedBits...
					   else							///< Inner predicted point is now upper point.
					   {
						   Du	= Dmax;
						   Ru	= R;
						   /// pQ[] must be reset to lower vector to maintain a descent convergence.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
					   }//end else...

				   }//end else...

				   iterations++;
			   }//end while !done...

			   /// Set the macroblock QP values to their found states.
		   if(invalidated)
		   {
				 for(mb = 0; mb < len; mb++)
				 {
					 _codec->_pMb[mb]._mbQP    = _pQ[mb];
					 _codec->_pMb[mb]._mbEncQP = _pQ[mb];
				 }//end for mb...
		   }//end if invalidated...

		 }//end if Rl...
		 */
		 ///======================================================================================
		 /*
		 /// Simple Truncation Algorithm

			 /// If QP = H264V2_MAX_QP and still does not fit then a truncation process is nessecary. The truncation
			 /// is somewhere between every mb encoded with motion with zero'ed coeffs and some mbs with max QP. The
		 /// _rate[0] member of the mbs holds the min encoding and is zero for skipped. Proceed by encoding each
		 /// skip run and max QP pair per mb and then count the bits to the end.
			 R         = 0;	///< Reset.
		 mbSkipRun = 0;
			 for(mb = 0; mb < len; mb++)
			 {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Do mb encoding including motion and max QP.
			   pMb->_mbQP = H264V2_MAX_QP;
			   R += _codec->ProcessInterMbImplStd(pMb, 0, 1);  ///< Returns 0 if skipped.
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;

			 /// Add up min encodings from the next mb to the end.
			 int bitsToEnd = 0;
			 int run       = 0;
			 int mbi       = mb + 1;
			 while(mbi < len)
			 {
			   MacroBlockH264* pMbi = &(_codec->_pMb[mbi]);
			   int r = pMbi->_rate[0];
			   if(r) ///< Not skipped.
			   {
				 bitsToEnd += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(run));
				 run = 0;
			   }//end if r...
			   else
				 run++;
			   mbi++;
			 }//end while mbi...
			 if(run)
				bitsToEnd += _codec->_pHeaderUnsignedVlcEnc->Encode(run);

			 /// With this mb max QP encoded and min encoding for all remaining mbs to the end,
			 /// if it does not fit then mark it as the min encoding point and break.
			 if((R + bitsToEnd) >= allowedBits)
			 {
					   minMBIndex = mb;
					   break;
			 }//end if R...
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			 }//end for mb...
		 */
}//end DamageControl.

/** Encode the image data for Inter pictures with a Dmax criterion.
Process all macroblocks in order with a mb Dmax limit and only write the result
to the ref image space if the writeRef code is set. Bit 1 of writeRef refers to
motion compensation and bit 0 to adding the difference to the ref. The motion
estimation process with its associated data structures is assumed to have been
completed before this method is called. The macroblock obj is prepared for
coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;
	int coeffBits = 0;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  ///---------------------- Macroblock Process ------------------------------------------
	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
		{
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);
		}//end if compRef...

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this mb as the median of the neighbourhood 
		/// vectors and subtract it from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
	  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;

		/// For desperate measures when the previous encoding failed to reach the targetted rate then 
		/// a further quantisation process can be implemented here where the coeffs will be zeroed. This
		/// has been tested but is not implemented because the effectiveness is limited.
		if (_codec->_pRateCntlPFrames != NULL)
		{
			if (_codec->_pRateCntlPFrames->OutOfBounds() && _codec->_pRateCntlPFrames->LowerDistortionOverflow())
				pMb->_mbQP = H264V2_MAX_QP + 16;
		}//end if _pRateCntlPFrames...

			/// Include all macroblocks.
		pMb->_include = 1;
		/// Find QP where the mb Lum dist is just below Dmax for this mb. Count the bits for the coeffs only.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessInterMbImplStd(pMb, addRef, 3, dmax, qEnd);
		else
			_codec->ProcessInterMbImplStd(pMb, addRef, 2, dmax, qEnd);

	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplDMax::Encode.

/** Decode the Inter macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Prepare for motion compensation on a per macoblock basis.
	_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		///------------------- Motion compensation -----------------------------------------------------------
		if (pMb->_mbPartPredMode != MacroBlockH264::Inter_16x16)	///< Fixed at 16x16 mode for now.
		{
			_codec->_errorStr = "[H264V2::InterImgPlaneDecoderImplStdVer1::Decode] Only supports Inter_16x16 mode";
			return(0);
		}//end if !Inter_16x16...

		/// Compensate the vector and hope the encoder estimator ensured that
		/// all pels fall inside the image space. The motion vector was decoded
		/// from the vector differences in the ReadMacroBlockLayer() method.
		_codec->_pMotionCompensator->Compensate(lOffX, lOffY, pMb->_mvX[MacroBlockH264::_16x16], pMb->_mvY[MacroBlockH264::_16x16]);

		if (pMb->_coded_blk_pattern)
		{
			/// --------------------- Inverse Transform & Quantisation -------------------------------
			if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
				_codec->InverseTransAndQuantInter16x16MBlk(pMb, 0);

			/// --------------------- Image Storing into Ref -----------------------------------------
			/// Fill the image (difference) colour components from all the non-DC 4x4 
			/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
			MacroBlockH264::StoreBlks(pMb, _codec->_16x16, 0, 0, _codec->_8x8_0, _codec->_8x8_1, 0, 0, 0);

			/// --------------------- Add the prediction ---------------------------------------------
			/// Lum.
			_codec->_RefLum->SetOverlayDim(16, 16);
			_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
			_codec->_16x16->SetOverlayDim(16, 16);
			_codec->_16x16->SetOrigin(0, 0);
			_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add to ref Lum and leave result in ref img.
			/// Cb.
			_codec->_RefCb->SetOverlayDim(8, 8);
			_codec->_RefCb->SetOrigin(cOffX, cOffY);
			_codec->_8x8_0->SetOverlayDim(8, 8);
			_codec->_8x8_0->SetOrigin(0, 0);
			_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
			/// Cr.
			_codec->_RefCr->SetOverlayDim(8, 8);
			_codec->_RefCr->SetOrigin(cOffX, cOffY);
			_codec->_8x8_1->SetOverlayDim(8, 8);
			_codec->_8x8_1->SetOrigin(0, 0);
			_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

		}//end if _coded_blk_pattern...

	}//end for mb...

	return(1);
}//end InterImgPlaneDecoderImplStdVer1::Decode.

/*
-------------------------------------------------------------------------------------------
	Private helper methods for prediction tools.
-------------------------------------------------------------------------------------------
*/

/** Calc the median of 3 numbers.
@param x	:	1st num.
@param y	:	2nd num.
@param z	:	3rd num.
@return		: The median of x, y and z.
*/
int H264v2Codec::Median(int x, int y, int z)
{
	int min, max;

	// min = MIN(x,MIN(y,z)) and max = MAX(x,MAX(y,z)).
	if ((y - z) < 0) { min = y;	max = z; }
	else { min = z; max = y; }
	if (x < min) min = x;
	if (x > max) max = x;
	// Median.
	int result = x + y + z - min - max;

	return(result);
}//end Median.

void H264v2Codec::DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title)
{
	int i, j;

	MeasurementTable* pT = new MeasurementTable();

	int cols = pBlk->GetWidth();
	int rows = pBlk->GetHeight();

	pT->Create(cols, rows);
	for (j = 0; j < cols; j++)
	{
		pT->SetHeading(j, "");
		pT->SetDataType(j, MeasurementTable::INT);
	}//end for j...

	pT->SetTitle(title);
	for (i = 0; i < rows; i++)
		for (j = 0; j < cols; j++)
			pT->WriteItem(j, i, pBlk->Read(j, i));

	pT->Save(filename, ",", 1);

	delete pT;
}//end DumpBlock.

========== END FILE: H264v2Codec/new/H264v2Codec.cpp ==========

========== BEGIN FILE: H264v2Codec/new/H264v2Codec.h ==========
Bundle entry: 150
Original bytes: 31928
Original SHA-256: 4e17d11802b4c322825d844be1a8895ef31831d142d0c4639458515315cd13cb
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264v2Codec

TAG						: H264V2C

FILE NAME			: H264v2Codec.h

DESCRIPTION		: A 2nd generation of video codecs based on the H.264 standard
								implementation. The primary interface is ICodecv2 for access 
								and configuration.

COPYRIGHT			: (c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _H264V2CODEC_H
#define _H264V2CODEC_H

#pragma once
#include <cstddef>
#include "ICodecv2.h"
#include "ICodecInnerAccess.h"

#include "BlockH264.h"
#include "NalHeaderH264.h"
#include "SliceHeaderH264.h"
#include "SeqParamSetH264.h"
#include "PicParamSetH264.h"

#ifdef _WIN32
//#include "Windows.h"

//#define H264V2C_MICROSOFT_PARALLEL 1
#ifdef H264V2C_MICROSOFT_PARALLEL
  #include <ppl.h>
  #include <ppltasks.h>
  using namespace concurrency;
  using namespace std;
#endif
#endif

#ifdef H264V2_DUMP
/// For storing measurements during testing.
//#define H264V2_DUMP_HEADERS 1
//#define H264V2_DUMP_MB_RD_DATA 1
//#define H264V2_DUMP_TIMING 1
//#define H264V2_DUMP_FRM_RD_DATA 1
#include "MeasurementTable.h"
#endif

/// Dump filenames
#define H264V2_RATE_CNTL_PFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlPFrames.csv"
#define H264V2_RATE_CNTL_IFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlIFrames.csv"

// forward declarations
class RGBtoYUV420Converter;
class YUV420toRGBConverter;
class IBitStreamWriter;
class IBitStreamReader;
class OverlayMem2Dv2;
class IForwardTransform;
class IInverseTransform;
class VectorStructList;
class IMotionEstimator;
class IMotionCompensator;
class IMotionVectorPredictor;
class IVlcEncoder;
class IVlcDecoder;
class MacroBlockH264;
class H264MbImgCache;
class IRateControl;

class ConvYUV420_16toBGR24;
class RGBtoYUV420Converter16;

/*
===========================================================================
  Codec specific definitions.
===========================================================================
*/

/// Defined Modes of Operation for bit allocation stratergies - "mode of operation".
#define	H264V2_OPEN						        0	/// (Default) Slice QP defines the bit usage without control.
#define H264V2_MB_QP_MINMAX_ADAPTIVE	1	/// Macroblock QP is adapted to meet the frame bit target.
#define H264V2_MB_QP_AVG_ADAPTIVE	    2	/// Macroblock QP is adapted to meet an average bit target.
#define H264V2_MB_QP_DMAX_ADAPTIVE	  3	/// Macroblock QP is adapted to meet Dmax target.

/// For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE the following rate control model types may be set:
#define H264V2_RATE_CONTROL_MODEL_QUAD  0	/// Inverse quadratic model.
#define H264V2_RATE_CONTROL_MODEL_POW   1	/// Power model.
#define H264V2_RATE_CONTROL_MODEL_LOG   2	/// Inverse log model.
//#define H264V2_RATE_CONTROL_MODEL_MULTI 3	/// Combination model.

/// Seq and Pic param max encoded length.
#define	H264V2_ENC_PARAM_LEN            32

/// Use non-reversible CCIR-601 colour conversions.
//#define _CCIR601

/*
===========================================================================
  Class definition.
===========================================================================
*/
class H264v2Codec : public ICodecv2, public ICodecInnerAccess
{
  /// construction
public:
  H264v2Codec();
  virtual ~H264v2Codec();

  /// ICodecv2 Interface Implementation
public:

  int		GetParameter(const char* type, int* length, void* value);
  void	GetParameterName(int ordinal, const char** name, int* length);
  int		SetParameter(const char* type, const char* value);

  char* GetErrorStr(void) { return((char *)_errorStr); }
  int		Ready(void) { return(_codecIsOpen); }
  int		GetCompressedBitLength(void) { return((int)_bitStreamSize); }
  int		GetCompressedByteLength(void)
  {
    int x = (int)_bitStreamSize / 8; if (_bitStreamSize & 0x7) x++; return(x);
  }
  void* GetReference(int refNum) { return((void*)_pRLum); }

  void	Restart(void);
  int		Open(void);
  int		Close(void);
  int		Code(void* pSrc, void* pCmp, int codeParameter);
  int		Decode(void* pCmp, int bitLength, void* pDst);

  /// ICodecInnerAccess Interface Implementation
public:
  void* GetMember(const char* type, int* length);
  void	GetMemberName(int ordinal, const char** name, int* length);
  int		SetMember(const char* type, void* pValue);

  /// Codec parameters.
private:
  // Decode input framing: 0 = Annex-B, 1 = AVC1 four-byte lengths.
  int _inputFraming;
  int DecodeNAL(void* pNal, int nalByteLength, void* pDst);
  int DecodeInternal(void* pCmp, int bitLength, void* pDst, bool singleNal);
  /// Unique Codec identification.
  int		_idCode;																				///"codecid"
  /// The codec parameters are seperated into 2 categories. Those that are static throughout the
  /// life span of an Open()/Close() session and those that are dynamic and can be changed per
  /// picture Code()/Decode(). 

  /// -------------- Static Parameters ------------------------------------------------------ 
  /// Set before Open() and cleared at Close().

  /// Description of the source/destination image.
  int		_width;																					///< "width"
  int		_height;																				///< "height"
  int		_inColour;																			///< "incolour"
  int		_outColour;																			///< "outcolour"
  bool  _flip;                                          ///< "flip" Stores whether the internal color converters should flip the image during conversion.

  /// Modes of operation (bit allocation strategies).
  int		_modeOfOperation;																///< "mode of operation"
  int   _intraIterations;                               ///< "intra iteration limit"
  int   _interIterations;                               ///< "inter iteration limit"
  int   _timeLimitMs;                                   ///< "time limit msec"
  int   _rateControlModelType;                          ///< "rate control model type"  (Only valid for mode of operation = 2)

  /// Parameter set handling.
  int		_currSeqParam;																	///< "seq param set"
  int		_currPicParam;																	///< "pic param set"
  int		_genParamSetOnOpen;															///< "generate param set on open"
  int   _prependParamSetsToIPic;                        ///< "prepend param sets to i-pictures"

  int		_startCodeEmulationPrevention;									///< "start code emulation prevention"

  /// -------------- Dynamic Parameters ------------------------------------------------------ 
  /// Set before Code()/Decode(). Remain in effect until modified.

  /// Picture properties.
  int		_pictureCodingType;															///< "picture coding type"	(Will be interpreted into/from NAL type)
  int		_lastPicCodingType;															///< "last pic coding type"
  int		_pQuant;																				///< "quality"
  int   _minQPIntra;                                    ///< "minimum intra qp"
  int   _minQPInter;                                    ///< "minimum inter qp"

  /// I-Picture modifiers.
  int		_autoIPicture;																	///< "autoipicture"
  int		_iPictureMultiplier;														///< "ipicturemultiplier"
  int		_iPictureFraction;															///< "ipicturefraction"
  int		_iPictureDMaxMultiplier;												///< "ipicture dmax multiplier"
  int		_iPictureDMaxFraction;													///< "ipicture dmax fraction"

  int  _seqParamSetLog2MaxFrameNumMinus4;               ///< "seq param log2 max frame num minus 4"

  int  _dMax;                                           ///< "max distortion"
  int  _maxBitsPerFrame;                                ///< "max bits per frame"
  int  _numRateCntlFrames;                              ///< "num rate control frames"
  int  _rateOvershootPercent;                           ///< "rate overshoot percent"

  int _enableROIEncoding;                               ///< "enable roi encoding"

/// Attributes
private:
  /// Intermediate input/output YCbCr image mem members.
  int							_lumWidth;		/// pix width.
  int							_lumHeight;		/// pix height.
  short*					_pLum;				/// Space to compress from and decompress to.
  int							_chrWidth;
  int							_chrHeight;
  short*					_pChrU;
  short*					_pChrV;

  /// 2-D overlays for YCbCr picture mem.
  OverlayMem2Dv2*	_Lum;
  OverlayMem2Dv2*	_Cb;
  OverlayMem2Dv2*	_Cr;

  /// Reference image mem members.
  short*					_pRLum;
  short*					_pRChrU;
  short*					_pRChrV;

  /// 2-D overlays for YCbCr picture reference mem.
  OverlayMem2Dv2*	_RefLum;
  OverlayMem2Dv2*	_RefCb;
  OverlayMem2Dv2*	_RefCr;

  /// Temp 16x16 and 8x8 mem blocks for use during macroblock prediction.
  short*					_p16x16;
  OverlayMem2Dv2*	_16x16;
  short*					_p8x8_0;
  OverlayMem2Dv2*	_8x8_0;
  short*					_p8x8_1;
  OverlayMem2Dv2*	_8x8_1;

  /// Temp 4x4 blks for distortion calculations during transform and quant processes.
  BlockH264       _tmpBlk[4][4];

  /// Image caching.
  H264MbImgCache* _mbImg;

private:
  void				ResetMembers(void);
  int					CodeNonPicNALTypes(void* pCmp, int frameBitLimit);

  int					SetSeqParamSet(int index);
  int					WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int         WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int         ReadSeqParamVuiParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamVuiHrdParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					SetPicParamSet(int index, int seqRef);
  int					WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int					ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int					GetCodecParams(int picParamSet);

  int					WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);
  int					WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int         InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset);
  int         RemoveEmulationPrevention(IBitStreamReader* bsr);

  int					WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed);
  int					MacroBlockLayerBitCounter(MacroBlockH264* pMb);
  int					MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb);
  int					ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  void				ApplyLoopFilter(void);
  void				VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);
  void				HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);

  void				TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  int         GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP);
  int         TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD);

  void				TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);
  void				InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);
  void				InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);

  void				TransAndQuantInter16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  void				InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);

  int					GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode);
  void				GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  int					GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  void				GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
                                        OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr, OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr);

  int					Median(int x, int y, int z);
  static void DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title);

  /// The implementations of img plane encoders and decoders is done through a common
  /// interface and as private nested classes.
private:
  /// Common interface for img plane encoders and decoders as nested classes.
  class IImagePlaneEncoder
  {
  public:
    virtual ~IImagePlaneEncoder(void) { }
    virtual int Encode(int allowedBits, int* bitsUsed, int writeRef) = 0;
    virtual int Create(int length) { return(1); }
  };//end class IImagePlaneEncoder.
  friend class IImagePlaneEncoder;

  class IImagePlaneDecoder
  {
  public:
    virtual ~IImagePlaneDecoder(void) { }
    virtual int Decode(void) = 0;
  };//end class IImagePlaneDecoder.
  friend class IImagePlaneDecoder;

  /// Implementations of img plane encoders and decoders as nested classes of codec.

  /// Image Plane Encoders.

  class IntraImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// I-frame IDR baseline encoder.
  {
  public:
    IntraImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplStdVer1.
  friend class IntraImgPlaneEncoderImplStdVer1;

  class IntraImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< I-frame macroblock level Quant adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. 
  public:
    IntraImgPlaneEncoderImplMinMax(H264v2Codec* codec) { _codec = codec; _pQ = NULL; _pQl = NULL; _pMbList = NULL; }
    virtual ~IntraImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[3 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pMbList = _pQl + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pMbList;
  };//end class IntraImgPlaneEncoderImplMinMax.
  friend class IntraImgPlaneEncoderImplMinMax;

  class IntraImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    IntraImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplDMax.
  friend class IntraImgPlaneEncoderImplDMax;

  class InterImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// P-frame baseline encoder.
  {
  public:
    InterImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplStdVer1.
  friend class InterImgPlaneEncoderImplStdVer1;

  class InterImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< P-frame macroblock PQ adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. Uses bisection method to find optimal selection.
  public:
    InterImgPlaneEncoderImplMinMax(H264v2Codec* codec)
    {
      _codec = codec; _pQ = NULL; _pQl = NULL; _pDistortionDiff = NULL; _pMbList = NULL; _pLastMbCoded = NULL; _pLastMbQP = NULL;
    }
    virtual ~InterImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControlMvOnly(int allowedBits, int* bitsUsed);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[6 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pDistortionDiff = _pQl + length; _pMbList = _pDistortionDiff + length;
      _pLastMbCoded = _pMbList + length; _pLastMbQP = _pLastMbCoded + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pDistortionDiff;
    int*  _pMbList;
    int*  _pLastMbCoded;  ///< Audit trail.
    int*  _pLastMbQP;
  };//end class InterImgPlaneEncoderImplMinMax.
  friend class InterImgPlaneEncoderImplMinMax;

  class InterImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    InterImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplDMax.
  friend class InterImgPlaneEncoderImplDMax;

  /// Image Plane Decoders.

  class IntraImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// I-frame IDR baseline decoder.
  {
  public:
    IntraImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneDecoderImplStdVer1.
  friend class IntraImgPlaneDecoderImplStdVer1;

  class InterImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// P-frame baseline decoder.
  {
  public:
    InterImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneDecoderImplStdVer1.
  friend class InterImgPlaneDecoderImplStdVer1;

  /// Code refactoring methods.
  int   FitDistPowerModel(int rl, int dl, int ru, int du, int r);
  int   FitDistLinearModel(int rl, int dl, int ru, int du, int r);

  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP);
  void  CoeffZeroingQuantisation(MacroBlockH264* pMb);
  void  CoeffZeroingQuantisationVer2(MacroBlockH264* pMb);
  int   ProcessIntraMbImplStdMin(MacroBlockH264* pMb);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP);
  int   ProcessInterMbImplStdMin(MacroBlockH264* pMb);
  int   GetDeltaQP(MacroBlockH264* pMb);
  int   GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra);
  int   GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra);

  /// In-line methods. 

  /** Get the previous macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Previous Mb QP.
  */
  inline int GetPrevMbQP(MacroBlockH264* pMb);

  /** Get the next macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Next Mb QP.
  */
  inline int GetNextMbQP(MacroBlockH264* pMb);

  /** Get the ROI modified distortion value.
  The input distortion is modified and returned to reflect the region
  of interest bias.
  @param pMb    : Macroblock to operate on.
  @return       : Modified distortion.
  */
  inline int ROIDistortion(int mbIndex, int d)
  { if (_enableROIEncoding) return( (int)(0.5 + ((double)d * _roiMultiplier[mbIndex])) ); else return(d); }

  /** Run a high performance timer
  @return : A timer exists.
  */
  static double _cpuFreq;
  int _startTime;
  inline static int SetCounter(void) 
  {
#ifdef _WIN32
    _cpuFreq = 0.0;
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
	    return(0);
    _cpuFreq = double(li.QuadPart)/1000.0;  ///< In ms
    return(1);
#else
    return 0;
#endif
  }//end SetCounter.

  inline static double GetCounter(void)
  {
#ifdef _WIN32
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    if(_cpuFreq != 0)
      return( double(li.QuadPart)/_cpuFreq );
    else
      return(0.0);
#else
    return 0.0;
#endif
  }//end GetCounter.

/// Codec Status.
private:
	char*		_errorStr;
  char    _errorInfo[256];
	int			_codecIsOpen;
	int			_bitStreamSize;

/// Constants.
private:
	/// The id must be unique for every codec implementation.
	static const unsigned short H264V2_ID = 1003;

	/// List of all parameter names accessed via GetParameterName().
	static const int		PARAMETER_LEN;		///< "parameters".
	static const char*	PARAMETER_LIST[];	///< ...of PARAMETER_LEN.

	/// List of all member names accessed via GetMemberName().
	static const int		MEMBER_LEN;			///< "members".
	static const char*	MEMBER_LIST[];	///< ...of MEMBER_LEN.

	/// Scaling matrix for DC coeffs. Unknown reason.
	static const int dc4x4Scale[];
	static const int dc2x2Scale[];

	/// Test sampling point coordinates for Intra_16x16 and Intra_8x8 prediction mode selection.
	static const int test16X[];
	static const int test16Y[];
	static const int test16Limit[];
	static const int testZoom16X[];
	static const int testZoom16Y[];
	static const int testZoom16Len;
  static const int delta16[][2];
	static const int testZoom8[][2];
  static const int testZoom8Len;
	static const int test8X[];
	static const int test8Y[];
	static const int test8Limit[];

	static const int testPntPath16xy[][2];
	static const int testPntPath8xy[][2];

	/// Loop filter constants.
	static const int alpha[52]; 
	static const int beta[52];
	static const int indexAbS[3][52];

	/// Fast search on the macroblock distortion vs. QP curve 
	/// changes the step size.
	static const int MbStepSize[];
  static const int NextQPDec[];

  /// Motion lambda constants for TCP-like adaptation.
  static const double MVLAMBDA_MAX;
  static const double MVLAMBDA_STEP;
  static const double MVLAMBDA_MULT;
  static const double MVLAMBDA_STEADYSTATE;

/// Operational members.
private:
	/// Compressed data stream access members.
	IBitStreamWriter*			_pBitStreamWriter;
	IBitStreamReader*			_pBitStreamReader;

	/// An input colour converter.
        RGBtoYUV420Converter16 *_pInColourConverter;
	ConvYUV420_16toBGR24 *_pOutColourConverter;	

	/// 4x4 and 2x2 IT DC and AC transform filters.
	IForwardTransform* _pF4x4TLum;
	IForwardTransform* _pF4x4TChr;
	IForwardTransform* _pFDC4x4T;
	IForwardTransform* _pFDC2x2T;
	IInverseTransform* _pI4x4TLum;
	IInverseTransform* _pI4x4TChr;
	IInverseTransform* _pIDC4x4T;
	IInverseTransform* _pIDC2x2T;

	/// The motion estimator distortion is tested to	determine if an
	/// I-frame would be more appropriate for the frame. But for abs
	/// diff algorithms a different linear factor is required compared
	/// to squared error algorithms.
	int										_motionFactor;						///< Sqr Err = 4, Abs diff = 2.
	/// Auto I-frame detection test variable to hold the previous picture distortion.
	long									_prevMotionDistortion;
	///	Auto I-frame flags to indicate which macroblocks must be excluded
	/// from the decision during the motion estimation process.
	bool*									_autoIFrameIncluded;

	IMotionEstimator*			  _pMotionEstimator;				///< Selected estimator dependent on mode.
	VectorStructList*			  _pMotionEstimationResult;	///< Motion vector list generated by estimator.
	IMotionCompensator*		  _pMotionCompensator;			///< Selected compensator dependent on mode.
	VectorStructList*			  _pMotionVectors;					///< Motion vector list input to compensators.
  IMotionVectorPredictor* _pMotionPredictor;        ///< Predictor for motion vector from neighbouring mbs.

	/// Vlc encoders and decoders for use with CAVLC.
	IVlcEncoder*	_pPrefixVlcEnc;
	IVlcDecoder*	_pPrefixVlcDec;
	IVlcEncoder*	_pCoeffTokenVlcEnc;
	IVlcDecoder*	_pCoeffTokenVlcDec;
	IVlcEncoder*	_pTotalZeros4x4VlcEnc;
	IVlcDecoder*	_pTotalZeros4x4VlcDec;
	IVlcEncoder*	_pTotalZeros2x2VlcEnc;
	IVlcDecoder*	_pTotalZeros2x2VlcDec;
	IVlcEncoder*	_pRunBeforeVlcEnc;
	IVlcDecoder*	_pRunBeforeVlcDec;
	/// ... and the remaining vlc encoders and decoders.
	IVlcEncoder*	_pBlkPattVlcEnc;
	IVlcDecoder*	_pBlkPattVlcDec;
	IVlcEncoder*	_pDeltaQPVlcEnc;
	IVlcDecoder*	_pDeltaQPVlcDec = NULL;
	IVlcEncoder*	_pMbTypeVlcEnc;
	IVlcDecoder*	_pMbTypeVlcDec;
	IVlcEncoder*	_pMbIChrPredModeVlcEnc;
	IVlcDecoder*	_pMbIChrPredModeVlcDec;
	IVlcEncoder*	_pMbMotionVecDiffVlcEnc;
	IVlcDecoder*	_pMbMotionVecDiffVlcDec;
	/// Context-Aware vlc codecs for each block size.
	IContextAwareRunLevelCodec* _pCAVLC4x4;
	IContextAwareRunLevelCodec* _pCAVLC2x2;
	/// General header vlc encoders and decoders.
	IVlcEncoder*	_pHeaderUnsignedVlcEnc;
	IVlcDecoder*	_pHeaderUnsignedVlcDec;
	IVlcEncoder*	_pHeaderSignedVlcEnc;
	IVlcDecoder*	_pHeaderSignedVlcDec;

	/// Macroblocks for the image.
	int								_mbLength;	///< No. of 16 x 16 macroblocks for this image size.
	MacroBlockH264*		_pMb;				///< Base macroblock linear reference.
	MacroBlockH264**	_Mb;				///< Macroblock 2-D reference.

	/// Internal picture properties. (For now)

	/// NAL unit definition.
	NalHeaderH264		_nal;
	/// Parameter sets with their current selections that reference the parameter arrays. 
	SeqParamSetH264	_seqParam[32];
	PicParamSetH264	_picParam[255];
  int             _encSeqParamByteLen;
  unsigned char   _pEncSeqParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded seq param set. (32 bytes)
  int             _encPicParamByteLen;
  unsigned char   _pEncPicParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded pic param set. (32 bytes)

	/// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	/// control parameters to maintain a list of these references. However, in this implementation
	/// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	/// reference lists (List0) are maintained and frame number counting is consecutively incremented
	/// from the previous IDR-frame.
	int						_frameNum;				///< Used for SliceHeader._frame_num
	int						_maxFrameNum;			///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	int						_idrFrameNum;			///< Used for SliceHeader._idr_pic_id

	/// This implementation has only 1 slice for the entire frame without
	/// partitioning and therefore the slice parameters are simple.
	SliceHeaderH264	_slice;
	int							_mb_skip_run;		///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders. 
	IImagePlaneEncoder*		_pIntraImgPlaneEncoder;
	IImagePlaneEncoder*		_pInterImgPlaneEncoder;
	IImagePlaneDecoder*		_pIntraImgPlaneDecoder;
	IImagePlaneDecoder*		_pInterImgPlaneDecoder;

  /// Rate controllers and associated parameters.
  IRateControl*         _pRateCntlIFrames;
  IRateControl*         _pRateCntlPFrames;
  int                   _frameMSD;
  int                   _frameMAD;
  int                   _frameMAD_N;
  double                _predFrmMAD;
  int                   _avgBitsPerFrame;
  double                _coeffBitsPerPel;

  /// Region of Interest encoding parameters.
  double*               _roiMultiplier; ///< Multiply the distortion by a factor between 0.0..1.0 per macroblock.

  /// Motion lambda parameter for TCP-like adaptation.
  double                _mvLambda;  

#ifdef H264V2_DUMP
#ifdef H264V2_DUMP_HEADERS
  MeasurementTable _headerTable;
  int _headerTableLen;
  int _headerTablePos;
#endif
#ifdef H264V2_DUMP_MB_RD_DATA
  MeasurementTable _mbRDTable;
  int _mbRDTableLen;
  int _mbRDTablePos;
#endif
#ifdef H264V2_DUMP_TIMING
  MeasurementTable _timingTable;
  int _timingTableLen;
  int _timingTablePos;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
  MeasurementTable _frmRDTable;
  int _frmRDTableLen;
  int _frmRDTablePos;
#endif
#endif

};//H264v2Codec class.


#endif	//end _H264V2CODEC_H
========== END FILE: H264v2Codec/new/H264v2Codec.h ==========

========== BEGIN FILE: H264v2Codec/old/H264v2Codec.cpp ==========
Bundle entry: 151
Original bytes: 518186
Original SHA-256: b13810b59c2d7cb9c452ffb8fe5597fb6f74673ff23c9a403b8e0f6bae8c44bf
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE        : H264v2Codec

TAG           : H264V2

FILE NAME     : H264v2Codec.cpp

DESCRIPTIONS  : A 2nd generation of video codecs based on the H264 standard
				        implementation. The primary interface is ICodecv2 for access
				        and configuration.

COPYRIGHT	    : (c)CSIR 2007-2017 all rights resevered

LICENSE		    : Software License Agreement (BSD License)

RESTRICTIONS  : Redistribution and use in source and binary forms, with or without
								modification, are permitted provided that the following conditions
								are met:

								* Redistributions of source code must retain the above copyright notice,
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice,
								this list of conditions and the following disclaimer in the documentation
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used
								to endorse or promote products derived from this software without specific
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================*/

#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#else
#include <stdio.h>
#endif

#include <cstdio>
#include <memory.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include "H264v2Codec.h"

/// Macros
#include "CodecDistortionDef.h"

#include "ConvYUV420_16toRGB.h"
#include "ConvRGB24toYUV420v16FixP.h"
#include "ConvYUV420_16toRGB.h"
//#include "RGBtoYUV420Converter.h"
//#include "YUV420toRGBConverter.h"

#include "IBitStreamWriter.h"
#include "IBitStreamReader.h"
#include "OverlayMem2Dv2.h"
#include "IForwardTransform.h"
#include "IInverseTransform.h"
#include "IRunLengthCodec.h"
#include "VectorStructList.h"
#include "IMotionEstimator.h"
#include "IMotionCompensator.h"
#include "IMotionVectorPredictor.h"
#include "IVlcEncoder.h"
#include "IVlcDecoder.h"
#include "MacroBlockH264.h" 
#include "H264MbImgCache.h"
#include "IRateControl.h"

/// Implementations.
#include "BitStreamWriterMSB.h"
#include "BitStreamReaderMSB.h"

//#include "RealRGB24toYUV420CCIR601ConverterVer16.h"
//#include "RealYUV420toRGB24CCIR601ConverterVer16.h"	
//#include "RealRGB24toYUV420ConverterImpl2Ver16.h"
//#include "RealYUV420toRGB24ConverterImpl2Ver16.h"

#include "FastForward4x4ITImpl2.h"
#include "FastForward4x4ITImpl1.h"
#include "FastInverse4x4ITImpl1.h"
#include "FastForwardDC4x4ITImpl1.h"
#include "FastInverseDC4x4ITImpl1.h"
#include "FastForwardDC2x2ITImpl1.h"
#include "FastInverseDC2x2ITImpl1.h"
#include "FastForward4x4On16x16ITImpl1.h"
#include "FastInverse4x4On16x16ITImpl1.h"
#include "CAVLCH264Impl.h"
#include "CAVLCH264Impl2.h"

#include "MotionEstimatorH264ImplMultires.h"
#include "MotionEstimatorH264ImplMultiresCross.h"
#include "MotionEstimatorH264ImplCross.h"
#include "MotionEstimatorH264ImplMultiresCrossVer2.h"
#include "MotionEstimatorH264ImplFull.h"
#include "MotionEstimatorH264ImplTest.h"
#include "MotionCompensatorH264ImplStd.h"
#include "H264MotionVectorPredictorImpl1.h"


#include "PrefixH264VlcEncoderImpl1.h"
#include "PrefixH264VlcDecoderImpl1.h"
#include "CoeffTokenH264VlcEncoder.h"
#include "CoeffTokenH264VlcDecoder.h"
#include "TotalZeros4x4H264VlcEncoder.h"
#include "TotalZeros4x4H264VlcDecoder.h"
#include "TotalZeros2x2H264VlcEncoder.h"
#include "TotalZeros2x2H264VlcDecoder.h"
#include "TotalZeros2x4H264VlcEncoder.h"
#include "TotalZeros2x4H264VlcDecoder.h"
#include "RunBeforeH264VlcEncoder.h"
#include "RunBeforeH264VlcDecoder.h"
#include "ExpGolombUnsignedVlcEncoder.h"
#include "ExpGolombUnsignedVlcDecoder.h"
#include "ExpGolombSignedVlcEncoder.h"
#include "ExpGolombSignedVlcDecoder.h"
#include "ExpGolombTruncVlcEncoder.h"
#include "ExpGolombTruncVlcDecoder.h"
#include "CodedBlkPatternH264VlcEncoder.h"
#include "CodedBlkPatternH264VlcDecoder.h"

#include "RateControlImplQuad.h"
#include "RateControlImplPow.h"
#include "RateControlImplLog.h"
//#include "RateControlImplMultiModel.h"  An incomplete work in progress.

/*
---------------------------------------------------------------------------
  Codec parameter constants.
---------------------------------------------------------------------------
*/
/// Picture type definitions. Values for _pictureCodingType member.
#define H264V2_INTRA				0
#define H264V2_INTER				1
#define H264V2_SEQ_PARAM		2
#define H264V2_PIC_PARAM		3

#define H264V2_I_PIC				0
#define H264V2_P_PIC				1
#define H264V2_PB_PIC				2
#define H264V2_B_PIC				3
#define H264V2_EI_PIC				4
#define H264V2_EP_PIC				5

#define H264V2_MAX_QP							  51	///< Maximum QP value
#define H264V2_MAX_EXT_QP	          71	///< Maximum extended QP value for Inter
#define H264V2_I_MAX_EXT_QP	        85	///< Maximum extended QP value for Intra

#define H264V2_MAX_INTRA_ITERATIONS	5 	///< Default settings for a limit on optimisation iterations for slow convergence.
#define H264V2_MAX_INTER_ITERATIONS	10 

/*
---------------------------------------------------------------------------
  Colour space constants.
---------------------------------------------------------------------------
*/
#define H264V2_RGB24							0		///< 888 (Default).
#define H264V2_RGB32							1		///< 8888.
#define H264V2_RGB16							2		///< 565.

#define H264V2_YUV420P16					16	///< Planar Y, U then V (16 bits/component).
#define H264V2_YUV420P8						17	///< Planar Y, U then V (8 bits/component).

/*
--------------------------------------------------------------------------
  Macros.
--------------------------------------------------------------------------
*/
#define H264V2_CLIP31(x)	( (((x) <= 31)&&((x) >= 1))? (x) : ( ((x) < 1)? 1:31 ) )
#define H264V2_CLIP51(x)	( (((x) <= 31)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:51 ) )
#define H264V2_CLIP255(x)	( (((x) <= 255)&&((x) >= 0))? (x) : ( ((x) < 0)? 0:255 ) )

#undef	H264V2_EXACT_DMAX

#define H264V2_FAST_ABS32(x) ( ((x)^((x)>>31))-((x)>>31) )
#define H264V2_FAST_ABS16(x) ( ((x)^((x)>>15))-((x)>>15) )

/*
--------------------------------------------------------------------------
  Local constants.
--------------------------------------------------------------------------
*/
const int		H264v2Codec::PARAMETER_LEN = 35;
const char*	H264v2Codec::PARAMETER_LIST[] =
{
	"parameters",								            // 0
	"codecid",									            // 1
	"width",										            // 2
	"height",										            // 3
	"incolour",									            // 4
	"outcolour",								            // 5
  "flip",                                 // 6
	"picture coding type",			            // 7
	"last pic coding type",			            // 8
	"quality",									            // 9
	"autoipicture",							            // 10 
	"ipicturemultiplier",				            // 11
	"ipicturefraction",					            // 12
	"mode of operation",				            // 13
	"intra iteration limit",				        // 14
	"inter iteration limit",				        // 15
	"time limit msec",				              // 16
  "rate control model type",              // 17
	"seq param set",						            // 18
	"pic param set",						            // 19
	"gen param set on open",		            // 20
  "prepend param sets to i-pictures",     // 21
	"start code emulation prevention",      // 22
  "idr frame number",                     // 23
  "p frame number",                       // 24
  "seq param log2 max frame num minus 4", // 25
  "minimum intra qp",                     // 26
  "minimum intra qp",                     // 27
  "max distortion",                       // 28
  "num rate control frames",              // 29
  "max bits per frame",                   // 30
  "ipicture dmax multiplier",             // 31
  "ipicture dmax fraction",               // 32
  "rate overshoot percent",               // 33
  "enable roi encoding"                   // 34
};

const int		H264v2Codec::MEMBER_LEN = 7;
const char*	H264v2Codec::MEMBER_LIST[] =
{
	"members",									// 0
	"macroblocks",							// 1
  "reference",                // 2
	"autoiframedetectflag",			// 3
  "roi multiplier",			      // 4
  "currseqparamset",          // 5
  "currpicparamset"           // 6
};

/// Scaling is required for the DC coeffs to match the 4x4 
/// inverse IT scaling of the AC coeffs. Standard defines 
/// default Flat_4x4_16 for DC scaling.
const int H264v2Codec::dc4x4Scale[16] =
{ 16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16,
	16, 16, 16, 16
};
const int H264v2Codec::dc2x2Scale[4] =
{ 16, 16,
	16, 16
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a grid defined by the method used in 
/// the Packet Video Conference Proceedings 2015 in a paper by K.T. Luhandjula and K.L. Ferguson entitled "Sampling 
/// Point Path Selection for Fast Intra Mode Prediction".
#define H264V2_16x16_PATH_LENGTH 20

const int H264v2Codec::testPntPath16xy[256][2] =
{
  {10,10},{7,5},{13,14},{3,12},{12,3},{5,8},{15,6},{7,13},{2,3},{10,1},{1,9},{12,9},{5,15},{6,2},{14,11},{9,7}, ///< 0-15
  {2,6},{14,2},{8,12},{4,4},{1,14},{11,6},{11,15},{5,0},{7,10},{0,11},{9,4},{15,10},{13,5},{4,7},{3,1},{10,13}, ///< 16-31
  {12,0},{4,11},{0,3},{8,8},{8,2},{3,14},{15,14},{6,7},{1,5},{12,12},{14,4},{3,9},{6,12},{13,7},{11,1},{0,7},   ///< 32-47
  {9,9},{5,4},{9,15},{2,10},{11,8},{4,0},{9,3},{1,12},{14,9},{7,1},{5,13},{15,1},{10,11},{0,2},{3,4},{13,15},   ///< 48-63
  {10,5},{7,14},{5,10},{12,2},{2,8},{13,11},{8,6},{0,14},{1,1},{15,8},{7,3},{9,0},{3,6},{11,12},{4,15},{14,3},  ///< 64-79
  {6,10},{14,13},{6,6},{10,7},{0,9},{4,2},{12,6},{8,14},{2,13},{2,0},{13,9},{9,8},{1,3},{6,1},{4,12},{6,4},     ///< 80-95
  {2,5},{11,11},{15,13},{1,11},{10,2},{1,4},{14,5},{8,11},{10,15},{3,8},{7,0},{0,6},{2,15},{15,0},{5,3},{14,8}, ///< 96-111
  {6,11},{12,14},{9,5},{7,7},{4,10},{9,13},{13,4},{11,9},{3,3},{4,6},{0,12},{5,1},{6,14},{14,12},{15,2},{9,10}, ///< 112-127
  {7,2},{1,7},{12,8},{4,9},{8,3},{3,13},{10,0},{12,5},{7,9},{15,7},{11,13},{7,15},{1,2},{5,6},{13,10},{11,3},   ///< 128-143
  {2,11},{15,15},{0,0},{1,15},{2,1},{10,6},{8,4},{5,12},{12,11},{11,0},{4,8},{9,8},{1,3},{6,1},{13,3},{13,13},  ///< 144-159
  {5,9},{9,12},{2,7},{15,4},{0,13},{9,14},{6,0},{3,5},{2,14},{13,6},{15,9},{8,5},{0,5},{11,10},{14,1},{3,7},    ///< 160-175
  {14,10},{8,13},{5,14},{3,2},{9,1},{1,10},{6,3},{11,7},{7,11},{12,15},{13,2},{2,9},{8,9},{10,4},{6,13},{4,1},  ///< 176-191
  {13,2},{2,9},{8,9},{10,4},{6,13},{4,1},{10,12},{0,8},{2,2},{3,11},{0,1},{10,8},{5,5},{14,7},{8,0},{0,10},     ///< 192-207
  {4,13},{6,5},{15,11},{11,2},{11,14},{8,7},{0,4},{8,10},{6,15},{13,12},{10,3},{7,4},{4,14},{1,8},{3,0},{12,7}, ///< 208-223
  {12,1},{5,11},{9,6},{4,3},{6,9},{4,5},{1,13},{15,12},{9,2},{10,14},{12,4},{1,0},{2,12},{10,9},{15,3},{5,2},   ///< 224-239
  {7,12},{14,14},{0,15},{13,8},{3,10},{14,0},{5,7},{9,11},{11,5},{1,6},{8,15},{8,1},{2,4},{12,13},{14,6},{6,8}  ///< 240-255
};
/*
const int H264v2Codec::testPntPath16xy[256][2] =
  {
	{0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},{0,12},{0,13},{0,14},{0,15}, ///< 0-15
	{1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},{1,12},{1,13},{1,14},{1,15}, ///< 16-31
	{2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},{2,12},{2,13},{2,14},{2,15}, ///< 32-47
	{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11},{3,12},{3,13},{3,14},{3,15}, ///< 48-63
	{4,0},{4,1},{4,2},{4,3},{4,4},{4,5},{4,6},{4,7},{4,8},{4,9},{4,10},{4,11},{4,12},{4,13},{4,14},{4,15}, ///< 64-79
	{5,0},{5,1},{5,2},{5,3},{5,4},{5,5},{5,6},{5,7},{5,8},{5,9},{5,10},{5,11},{5,12},{5,13},{5,14},{5,15}, ///< 80-95
	{6,0},{6,1},{6,2},{6,3},{6,4},{6,5},{6,6},{6,7},{6,8},{6,9},{6,10},{6,11},{6,12},{6,13},{6,14},{6,15}, ///< 96-111
	{7,0},{7,1},{7,2},{7,3},{7,4},{7,5},{7,6},{7,7},{7,8},{7,9},{7,10},{7,11},{7,12},{7,13},{7,14},{7,15}, ///< 112-127
	{8,0},{8,1},{8,2},{8,3},{8,4},{8,5},{8,6},{8,7},{8,8},{8,9},{8,10},{8,11},{8,12},{8,13},{8,14},{8,15}, ///< 128-143
	{9,0},{9,1},{9,2},{9,3},{9,4},{9,5},{9,6},{9,7},{9,8},{9,9},{9,10},{9,11},{9,12},{9,13},{9,14},{9,15}, ///< 144-159
	{10,0},{10,1},{10,2},{10,3},{10,4},{10,5},{10,6},{10,7},{10,8},{10,9},{10,10},{10,11},{10,12},{10,13},{10,14},{10,15}, ///< 160-175
	{11,0},{11,1},{11,2},{11,3},{11,4},{11,5},{11,6},{11,7},{11,8},{11,9},{11,10},{11,11},{11,12},{11,13},{11,14},{11,15}, ///< 176-191
	{12,0},{12,1},{12,2},{12,3},{12,4},{12,5},{12,6},{12,7},{12,8},{12,9},{12,10},{12,11},{12,12},{12,13},{12,14},{12,15}, ///< 192-207
	{13,0},{13,1},{13,2},{13,3},{13,4},{13,5},{13,6},{13,7},{13,8},{13,9},{13,10},{13,11},{13,12},{13,13},{13,14},{13,15}, ///< 208-223
	{14,0},{14,1},{14,2},{14,3},{14,4},{14,5},{14,6},{14,7},{14,8},{14,9},{14,10},{14,11},{14,12},{14,13},{14,14},{14,15}, ///< 224-239
	{15,0},{15,1},{15,2},{15,3},{15,4},{15,5},{15,6},{15,7},{15,8},{15,9},{15,10},{15,11},{15,12},{15,13},{15,14},{15,15}  ///< 240-255
  };
*/

#define H264V2_8x8_PATH_LENGTH 5

const int H264v2Codec::testPntPath8xy[64][2] =
{
  {5,5},{3,3},{7,7},{2,6},{6,1},{2,4},{7,3},{3,6},    ///< 0-7
  {1,2},{5,0},{0,4},{6,4},{2,7},{3,1},{7,5},{4,3},    ///< 8-15
  {1,3},{7,1},{4,6},{2,2},{0,7},{5,3},{5,7},{2,0},    ///< 16-23
  {3,5},{0,5},{4,2},{7,4},{6,2},{2,3},{1,0},{5,6},    ///< 24-31
  {6,0},{0,1},{4,4},{4,1},{1,7},{6,6},{3,4},{0,2},    ///< 32-39
  {6,5},{7,2},{1,4},{3,7},{6,3},{5,1},{0,3},{4,5},    ///< 40-47
  {3,2},{4,7},{1,5},{5,4},{2,1},{5,2},{0,6},{7,6},    ///< 48-55
  {3,0},{2,5},{7,0},{6,7},{1,1},{0,0},{4,0},{1,6}     ///< 56-63
};

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a spread out grid.
const int H264v2Codec::test16X[256] = { 3, 11,  3, 11,
									1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,  1,  5,  9, 13,
									3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,  0,  7, 15,  0,  3,  7, 11, 15,
									0,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,
									5,  9, 13,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  1,  5,  9, 13,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  5,  9, 13,
									1,  2,  4,  6,  8, 10, 12, 14,  0,  3,  7, 11, 15,  0,  3, 11, 15,  6, 14,  0,  1,  9, 15,  0,  3, 11, 15,  0,  3, 11, 15,  0,  1, 15,  6, 14,  0,  9, 15,  0,  3, 11, 15,  1,  2,  4,  6,  8, 10, 12, 14,
									2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  6,  8, 10, 12, 14,  2,  4,  8, 10, 12,  2,  4,  6,  8, 10, 12, 14,
									1,  5,  7,  9, 13,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13,  1,  5,  7,  9, 13,  3,  5,  7,  9, 11, 13,  1,  3,  5,  7, 11, 13,  1,  5,  7,  9, 13 };
const int H264v2Codec::test16Y[256] = { 3,  3, 11, 11,
									1,  1,  1,  1,  5,  5,  5,  5,  9,  9,  9,  9, 13, 13, 13, 13,
									0,  0,  0,  0,  3,  3,  3,  7,  7,  7,  7,  7, 11, 11, 11, 15, 15, 15, 15, 15,
									0,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  6, 10, 10, 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14,
									0,  0,  0,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 15, 15, 15,
									0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,  8,  8,  8,  8, 10, 10, 10, 11, 11, 12, 12, 12, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
									1,  1,  1,  1,  1,  1,  1,  3,  3,  3,  3,  3,  5,  5,  5,  5,  5,  5,  5,  7,  7,  7,  7,  7,  7,  7,  9,  9,  9,  9,  9,  9,  9, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13,
									2,  2,  2,  2,  2,  4,  4,  4,  4,  4,  6,  6,  6,  6,  6,  8,  8,  8,  8,  8, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14 };
const int H264v2Codec::test16Limit[8] = { 4, 20, 40, 69, 123, 174, 219, 256 };

/// Test sampling point coordinates for Intra_16x16 prediction mode selection on a zooming square grid to be 
/// used 4 at a time where {(0,0), (0,8), (8,0), (8,8)} is added to each address in the table.
const int H264v2Codec::testZoom16X[21] =
{ 3,
  1, 5, 1, 5,
  0, 4, 0, 4,
  2, 6, 2, 6,
  0, 4, 0, 4,
  2, 6, 2, 6
};
const int H264v2Codec::testZoom16Y[21] =
{ 3,
  1, 1, 5, 5,
  0, 0, 4, 4,
  0, 0, 4, 4,
  2, 2, 6, 6,
  2, 2, 6, 6
};
const int H264v2Codec::testZoom16Len = 21;
const int H264v2Codec::delta16[4][2] = { {0,0}, {8,0}, {0,8}, {8,8} };
///< Thresholds for predicted final distortion = 20480/(256/4) = 320 (4 samples/mode completed)
#define H264V2_LUM_DISTORTION_THRESHOLD 320

const int H264v2Codec::testZoom8[5][2] = { {3,3}, {1,1}, {5,1}, {1,5}, {5,5} };
const int H264v2Codec::testZoom8Len = 5;
///< Thresholds for predicted final distortion = 10240/(128/2) = 160 (2 samples/mode completed)
#define H264V2_CHR_DISTORTION_THRESHOLD 160

/// Test sampling point coordinates for Intra_8x8 prediction mode selection.
const int H264v2Codec::test8X[64] = { 2, 5, 2, 5,
																			0, 4, 7, 0, 7, 0, 4, 7,
																			2, 5, 6, 1, 6, 0, 7, 3, 4, 3, 4, 0, 7, 1, 6, 2, 5,
																			1, 3, 0, 2, 3, 4, 5, 7, 1, 3, 4, 6, 0, 1, 2, 5, 6, 7, 1, 2, 5, 6, 1, 3, 4, 6, 0, 2, 3, 4, 5, 7, 1, 3, 6 };
const int H264v2Codec::test8Y[64] = { 2, 2, 5, 5,
																			0, 0, 0, 4, 4, 7, 7, 7,
																			0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
																			0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7 };
const int H264v2Codec::test8Limit[4] = { 4, 12, 29, 64 };

/// Loop filter constants.
const int H264v2Codec::alpha[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226, 255, 255 };
const int H264v2Codec::beta[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3,  4,  4,  4,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13,  14,  14,  15,  15,  16,  16,  17,  17,  18,  18 };
///                                           0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
const int H264v2Codec::indexAbS[3][52] = { { 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, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 8,10,11,12,13,15,17 },
																						{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13,14,16,18,20,23,25} };

/// Fast search on the macroblock distortion vs. QP curve changes the step size
/// depending on the QP value.
#ifdef H264V2_EXACT_DMAX
const int H264v2Codec::MbStepSize[H264V2_MAX_QP + 1] =
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
#else
const int H264v2Codec::MbStepSize[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	 1,	 1,	 1,	 2,	 2,	 2,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 2,	 3,	 3,	 3,	 3,	 3,	 3,	 3,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		3,	 3,	 3,	 3,	 3,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,	 4,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		4,	 4,	 4,	 4,  1,  2,  3,  4,  1,  2,  3,  4,  1,  2,  3,  4,
//  64  65  66  67  68  69  70  71
    1,   1,  1,  1,  1,  1,  1,  1
};
#endif
const int H264v2Codec::NextQPDec[H264V2_MAX_EXT_QP + 1] =
{//	0		1		2		3		4		5		6		7		8		9		10	11	12	13	14	15
		1,	1,	1,	2,	3,	4,	5,	6,	7,	8,	 9,	10,	11,	11,	13,	13,
//	16	17	18	19	20	21	22	23	24	25	26	27	28	29	30	31
		15,	15,	17,	17,	19,	19,	21,	21,	23,	23,	25,	25,	27,	27,	29,	29,
//	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47
		31,	31,	31,	31,	35,	35,	35,	35,	39,	39,	39,	39,	43,	43,	43,	43,
//	48	49	50	51  52  53  54  55  56  57  58  59  60  61  62  63  	
		47,	47,	47,	47, 51, 51, 51, 51, 55, 55, 55, 55, 59, 59, 59, 59,
//  64  65  66  67  68  69  70  71
		63, 63, 63, 63, 67, 68, 69, 70
};

/// CPU speed dependent high resolution timer.
double H264v2Codec::_cpuFreq = 0.0;

/// Motion lambda constants for TCP-like adaptation.
const double H264v2Codec::MVLAMBDA_MAX          = 4.0;
const double H264v2Codec::MVLAMBDA_STEP         = -0.1;
const double H264v2Codec::MVLAMBDA_MULT         = 0.5;
const double H264v2Codec::MVLAMBDA_STEADYSTATE  = 0.9;

/*
--------------------------------------------------------------------------
  Construction and destruction.
--------------------------------------------------------------------------
*/

H264v2Codec::H264v2Codec()
{
	ResetMembers();
}//end constructor.

void H264v2Codec::ResetMembers(void)
{
#ifdef H264V2_DUMP_HEADERS
	_headerTableLen = 300;
	_headerTable.Create(6, _headerTableLen);

	_headerTable.SetHeading(0, "NALType");
	_headerTable.SetHeading(1, "NALRefIdc");
	_headerTable.SetHeading(2, "IdrPicId");
	_headerTable.SetHeading(3, "FrmNum");
	_headerTable.SetHeading(4, "SliceType");
	_headerTable.SetHeading(5, "Qp");

	for (int j = 0; j < 6; j++)
		_headerTable.SetDataType(j, MeasurementTable::INT);

	_headerTablePos = 0;
#endif /// H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	int j;
	/// Collect macroblock R or D values for each QP for 64 macroblocks.
	_mbRDTableLen = 53;
	_mbRDTable.Create(65, _mbRDTableLen);  /// 1 for QP and 1 D value per mb

	_mbRDTable.SetHeading(0, "QP");
	_mbRDTable.SetHeading(1, "Distortion");
	for (j = 2; j < 65; j++)
		_mbRDTable.SetHeading(j, " ");

	for (j = 0; j < 65; j++)
		_mbRDTable.SetDataType(j, MeasurementTable::INT);

	/// 1st column is QP value for all mbs.
	_mbRDTable.WriteItem(0, 0, 0);
	for (j = 1; j < _mbRDTableLen; j++)
		_mbRDTable.WriteItem(0, j, j);

	_mbRDTablePos = 1;
#endif /// H264V2_DUMP_MB_RD_DATA
#ifdef H264V2_DUMP_TIMING
	_timingTableLen = 300;
	_timingTable.Create(2, _timingTableLen);

	_timingTable.SetHeading(0, "Frame");
	_timingTable.SetHeading(1, "Time (ms)");

	_timingTable.SetDataType(0, MeasurementTable::INT);
	_timingTable.SetDataType(1, MeasurementTable::INT);

	_timingTablePos = 0;
#endif /// H264V2_DUMP_TIMING

	_errorStr = "[H264v2Codec::ResetMembers] No error";
	_codecIsOpen = 0;
	_bitStreamSize = 0;

	/// Set default parameter values.
	_idCode = (int)H264V2_ID;
	_width = 176;
	_height = 144;
	_inColour = H264V2_RGB24;	///< Default to 24 bit rgb.
	_outColour = H264V2_RGB24;
	_flip = false;
	_pictureCodingType = H264V2_INTRA;
	_lastPicCodingType = H264V2_INTRA;
	_pQuant = 26;		///< Mid range [1..51].
	_minQPIntra = 16;   ///< Min QP value during mb optimisation
	_minQPInter = 4;
	_autoIPicture = 1;
	_iPictureMultiplier = 1;
	_iPictureFraction = 0;
	_iPictureDMaxMultiplier = 2;
	_iPictureDMaxFraction = 0;
	_dMax = 30000;    ///< Max distortion for all mbs with modeOfOperation = H264V2_MB_QP_DMAX_ADAPTIVE.
	_maxBitsPerFrame = 100240;   ///< This defines the max bit limit for modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_numRateCntlFrames = 12;     ///< Num of frames to do avg rate adaption over with  modeOfOperation = H264V2_MB_QP_AVG_ADAPTIVE.
	_rateOvershootPercent = 100;   ///< Percentage that the avg rate can be exceeded from frame to frame. 
	_coeffBitsPerPel = 0.0001;

	_modeOfOperation = H264V2_OPEN;
	_intraIterations = H264V2_MAX_INTRA_ITERATIONS;    ///< Intra optimisation iteration limit.
	_interIterations = H264V2_MAX_INTER_ITERATIONS;    ///< Inter optimisation iteration limit.
	_timeLimitMs = 0;  ///< Intra/inter optimisation time limit.
	_rateControlModelType = H264V2_RATE_CONTROL_MODEL_LOG;  ///< For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE.

	_currSeqParam = 0;	///< Index reference into _seqParam[32] array.
	_currPicParam = 0;	///< Index reference into _picParam[2] array.
	_genParamSetOnOpen = 1;	///< Generate the seq/pic parameter sets on the Open() call.
	_prependParamSetsToIPic = 1;  ///< Prepend a SPS and PPS NAL unit to the front of every I-Picture.

	_startCodeEmulationPrevention = 1;  ///< Enable/disable start code emulation prevention in bit stream.

	/// Work input image.
	_lumWidth = 0;
	_lumHeight = 0;
	_pLum = NULL;
	_chrWidth = 0;
	_chrHeight = 0;
	_pChrU = NULL;
	_pChrV = NULL;
	_Lum = NULL;
	_Cb = NULL;
	_Cr = NULL;
	/// Reference images.
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;
	_RefLum = NULL;
	_RefCb = NULL;
	_RefCr = NULL;

	/// Temp work mem.
	_p16x16 = NULL;
	_16x16 = NULL;
	_p8x8_0 = NULL;
	_8x8_0 = NULL;
	_p8x8_1 = NULL;
	_8x8_1 = NULL;

	/// Cache
	_mbImg = NULL;

	/// Colour converters.
	_pInColourConverter = NULL;
	_pOutColourConverter = NULL;
	/// Stream access.
	_pBitStreamWriter = NULL;
	_pBitStreamReader = NULL;
	/// IT transform filters.
	_pF4x4TLum = NULL;
	_pF4x4TChr = NULL;
	_pFDC4x4T = NULL;
	_pFDC2x2T = NULL;
	_pI4x4TLum = NULL;
	_pI4x4TChr = NULL;
	_pIDC4x4T = NULL;
	_pIDC2x2T = NULL;

	/// For motion estimation (and compensation).
	_motionFactor             = 2; ///< Default for abs diff algorithms.
	_prevMotionDistortion     = -1;
	_autoIFrameIncluded       = NULL;
	_pMotionEstimator         = NULL;
	_pMotionEstimationResult  = NULL;
	_pMotionCompensator       = NULL;
	_pMotionVectors           = NULL;
	_pMotionPredictor         = NULL;

	/// Vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = NULL;
	_pPrefixVlcDec = NULL;
	_pCoeffTokenVlcEnc = NULL;
	_pCoeffTokenVlcDec = NULL;
	_pTotalZeros4x4VlcEnc = NULL;
	_pTotalZeros4x4VlcDec = NULL;
	_pTotalZeros2x2VlcEnc = NULL;
	_pTotalZeros2x2VlcDec = NULL;
	_pRunBeforeVlcEnc = NULL;
	_pRunBeforeVlcDec = NULL;
	/// ... and the remaining vlc encoders and decoders.
	_pBlkPattVlcEnc = NULL;
	_pBlkPattVlcDec = NULL;
	_pDeltaQPVlcEnc = NULL;
	_pDeltaQPVlcDec = NULL;
	_pMbTypeVlcEnc = NULL;
	_pMbTypeVlcDec = NULL;
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	/// The CAVLC codecs.
	_pCAVLC4x4 = NULL;
	_pCAVLC2x2 = NULL;
	/// General header vlc encoders and decoders.
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// Macroblock data objects.
	_pMb = NULL;
	_Mb = NULL;

	/// Internal parameters.

	  /// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	  /// control parameters to maintain a list of these references. However, in this implementation
	  /// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	  /// reference lists (List0) are maintained and frame number counting is consecutively incremented
	  /// from the previous IDR-frame.
	_seqParamSetLog2MaxFrameNumMinus4 = 12;         ///< Range [0..12] made available as a codec parameter.
	_frameNum = 0;				  ///< Used for SliceHeader._frame_num
	_maxFrameNum = 1 << (_seqParamSetLog2MaxFrameNumMinus4 + 4);	///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	_idrFrameNum = 0;				  ///< Used for SliceHeader._idr_pic_id

	/// Slice without partitioning and therefore the slice parameters are simple. (Only one slice/frame.)
	_slice._type = SliceHeaderH264::I_Slice_All;	///< I-Slice/P-Slice.
	_slice._qp = _pQuant;	                    ///< Same as _pQuant for this implementation.
	_slice._qp_delta = 0;				                    ///< = 0 for this implementation.
	_slice._disable_deblocking_filter_idc = 0;
	_mb_skip_run = 0;				                    ///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders.
	_pIntraImgPlaneEncoder = NULL;
	_pInterImgPlaneEncoder = NULL;
	_pIntraImgPlaneDecoder = NULL;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	_pRateCntlPFrames = NULL;
	_pRateCntlIFrames = NULL;
  
  /// Region of Interest encoding.
  _roiMultiplier      = NULL;
  _enableROIEncoding  = 0; ///< Default is off.

	/// Motion vector Le Grange multiplier adaptation.
	_mvLambda = MVLAMBDA_STEADYSTATE;

	/// Timer
	_startTime = 0;

}//end ResetMembers.

H264v2Codec::~H264v2Codec()
{
	// If open then close first before exiting.
	if (_codecIsOpen)
		Close();
}//end destructor.

/*
-----------------------------------------------------------------------
  Parameter interface functions.
-----------------------------------------------------------------------
*/
int	H264v2Codec::GetParameter(const char* type, int*	length, void*	value)
{

	char *p = (char *)type;
	int len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		//_itoa(_pictureCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _pictureCodingType);
	else if (strncmp(p, "last pic coding type", len) == 0)
		//_itoa(_lastPicCodingType,(char *)value,10);
		sprintf((char *)value, "%d", _lastPicCodingType);
	else if (strncmp(p, "idr frame number", len) == 0)
		//_itoa(_idrFrameNum,(char *)value,10);
		sprintf((char *)value, "%d", _idrFrameNum);
	else if (strncmp(p, "p frame number", len) == 0)
		//_itoa(_frameNum,(char *)value,10);
		sprintf((char *)value, "%d", _frameNum);
	else if (strncmp(p, "width", len) == 0)
		//_itoa(_width,(char *)value,10);
		sprintf((char *)value, "%d", _width);
	else if (strncmp(p, "height", len) == 0)
		//_itoa(_height,(char *)value,10);
		sprintf((char *)value, "%d", _height);
	else if (strncmp(p, "incolour", len) == 0)
		//_itoa(_inColour,(char *)value,10);
		sprintf((char *)value, "%d", _inColour);
	else if (strncmp(p, "outcolour", len) == 0)
		//_itoa(_outColour,(char *)value,10);
		sprintf((char *)value, "%d", _outColour);
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = _flip ? 1 : 0;
		sprintf((char *)value, "%d", i);
	}
	else if (strncmp(p, "quality", len) == 0)
		//_itoa(_pQuant,(char *)value,10);
		sprintf((char *)value, "%d", _pQuant);
	else if (strncmp(p, "autoipicture", len) == 0)
		//_itoa(_autoIPicture,(char *)value,10);
		sprintf((char *)value, "%d", _autoIPicture);
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		//_itoa(_iPictureMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureMultiplier);
	else if (strncmp(p, "ipicturefraction", len) == 0)
		//_itoa(_iPictureFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureFraction);
	else if (strncmp(p, "codecid", len) == 0)
		//_itoa(_idCode,(char *)value,10);
		sprintf((char *)value, "%d", _idCode);
	else if (strncmp(p, "mode of operation", len) == 0)
		//_itoa(_modeOfOperation,(char *)value,10);
		sprintf((char *)value, "%d", _modeOfOperation);
	else if (strncmp(p, "intra iteration limit", len) == 0)
		//_itoa(_intraIterations,(char *)value,10);
		sprintf((char *)value, "%d", _intraIterations);
	else if (strncmp(p, "inter iteration limit", len) == 0)
		//_itoa(_interIterations,(char *)value,10);
		sprintf((char *)value, "%d", _interIterations);
	else if (strncmp(p, "time limit msec", len) == 0)
		//_itoa(_timeLimitMs,(char *)value,10);
		sprintf((char *)value, "%d", _timeLimitMs);
	else if (strncmp(p, "rate control model type", len) == 0)
		//_itoa(_rateControlModelType,(char *)value,10);
		sprintf((char *)value, "%d", _rateControlModelType);
	else if (strncmp(p, "seq param set", len) == 0)
		//_itoa(_currSeqParam,(char *)value,10);
		sprintf((char *)value, "%d", _currSeqParam);
	else if (strncmp(p, "pic param set", len) == 0)
		//_itoa(_currPicParam,(char *)value,10);
		sprintf((char *)value, "%d", _currPicParam);
	else if (strncmp(p, "generate param set on open", len) == 0)
		//_itoa(_genParamSetOnOpen,(char *)value,10);
		sprintf((char *)value, "%d", _genParamSetOnOpen);
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		//_itoa(_prependParamSetsToIPic,(char *)value,10);
		sprintf((char *)value, "%d", _prependParamSetsToIPic);
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		//_itoa(_startCodeEmulationPrevention,(char *)value,10);
		sprintf((char *)value, "%d", _startCodeEmulationPrevention);
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		//_itoa(_seqParamSetLog2MaxFrameNumMinus4,(char *)value,10);
		sprintf((char *)value, "%d", _seqParamSetLog2MaxFrameNumMinus4);
	else if (strncmp(p, "minimum intra qp", len) == 0)
		//_itoa(_minQPIntra,(char *)value,10);
		sprintf((char *)value, "%d", _minQPIntra);
	else if (strncmp(p, "minimum inter qp", len) == 0)
		//_itoa(_minQPInter,(char *)value,10);
		sprintf((char *)value, "%d", _minQPInter);
	else if (strncmp(p, "max distortion", len) == 0)
		//_itoa(_dMax,(char *)value,10);
		sprintf((char *)value, "%d", _dMax);
	else if (strncmp(p, "num rate control frames", len) == 0)
		//_itoa(_numRateCntlFrames,(char *)value,10);
		sprintf((char *)value, "%d", _numRateCntlFrames);
	else if (strncmp(p, "max bits per frame", len) == 0)
		//_itoa(_maxBitsPerFrame,(char *)value,10);
		sprintf((char *)value, "%d", _maxBitsPerFrame);
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		//_itoa(_iPictureDMaxMultiplier,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxMultiplier);
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		//_itoa(_iPictureDMaxFraction,(char *)value,10);
		sprintf((char *)value, "%d", _iPictureDMaxFraction);
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		//_itoa(_rateOvershootPercent,(char *)value,10);
		sprintf((char *)value, "%d", _rateOvershootPercent);
  else if (strncmp(p, "enable roi encoding", len) == 0)
    sprintf((char *)value, "%d", _enableROIEncoding);
  else if (strncmp(p, "parameters", len) == 0)
		//_itoa(PARAMETER_LEN,(char *)value,10);
		sprintf((char *)value, "%d", PARAMETER_LEN);
	else
	{
		_errorStr = "[H264v2Codec::GetParameter] Read parameter not supported";
		return(0);
	}//end else...

	*length = (int)strlen((char *)value);
	return(1);

	return(0);
}//end GetParameter.

void H264v2Codec::GetParameterName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= PARAMETER_LEN))
		return;
	*name = (const char *)PARAMETER_LIST[ordinal];
	*length = (int)strlen(PARAMETER_LIST[ordinal]);

}//end GetParameterName.

int H264v2Codec::SetParameter(const char* type, const char* value)
{

	char *p = (char *)type;
	char *v = (char *)value;
	int  len = (int)strlen(p);

	/// Most frequently called params at the top of the comparison list.
	if (strncmp(p, "picture coding type", len) == 0)
		_pictureCodingType = (int)(atoi(v));
	else if (strncmp(p, "idr frame number", len) == 0)
		_idrFrameNum = (int)(atoi(v));
	else if (strncmp(p, "p frame number", len) == 0)
		_frameNum = (int)(atoi(v));
	else if (strncmp(p, "width", len) == 0)
		_width = (int)(atoi(v));
	else if (strncmp(p, "height", len) == 0)
		_height = (int)(atoi(v));
	else if (strncmp(p, "incolour", len) == 0)
		_inColour = (int)(atoi(v));
	else if (strncmp(p, "outcolour", len) == 0)
		_outColour = (int)(atoi(v));
	else if (strncmp(p, "flip", len) == 0)
	{
		int i = (atoi)(v);
		_flip = (i != 0);
	}
	else if (strncmp(p, "quality", len) == 0)
		_pQuant = (int)(atoi(v));
	else if (strncmp(p, "autoipicture", len) == 0)
		_autoIPicture = (int)(atoi(v));
	else if (strncmp(p, "ipicturemultiplier", len) == 0)
		_iPictureMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicturefraction", len) == 0)
		_iPictureFraction = (int)(atoi(v));
	else if (strncmp(p, "mode of operation", len) == 0)
		_modeOfOperation = (int)(atoi(v));
	else if (strncmp(p, "intra iteration limit", len) == 0)
		_intraIterations = (int)(atoi(v));
	else if (strncmp(p, "inter iteration limit", len) == 0)
		_interIterations = (int)(atoi(v));
	else if (strncmp(p, "time limit msec", len) == 0)
		_timeLimitMs = (int)(atoi(v));
	else if (strncmp(p, "rate control model type", len) == 0)
		_rateControlModelType = (int)(atoi(v));
	else if (strncmp(p, "seq param set", len) == 0)
		_currSeqParam = (int)(atoi(v));
	else if (strncmp(p, "pic param set", len) == 0)
		_currPicParam = (int)(atoi(v));
	else if (strncmp(p, "generate param set on open", len) == 0)
		_genParamSetOnOpen = (int)(atoi(v));
	else if (strncmp(p, "prepend param sets to i-pictures", len) == 0)
		_prependParamSetsToIPic = (int)(atoi(v));
	else if (strncmp(p, "start code emulation prevention", len) == 0)
		_startCodeEmulationPrevention = (int)(atoi(v));
	else if (strncmp(p, "seq param log2 max frame num minus 4", len) == 0)
		_seqParamSetLog2MaxFrameNumMinus4 = (int)(atoi(v));
	else if (strncmp(p, "minimum intra qp", len) == 0)
		_minQPIntra = (int)(atoi(v));
	else if (strncmp(p, "minimum inter qp", len) == 0)
		_minQPInter = (int)(atoi(v));
	else if (strncmp(p, "max distortion", len) == 0)
		_dMax = (int)(atoi(v));
	else if (strncmp(p, "num rate control frames", len) == 0)
		_numRateCntlFrames = (int)(atoi(v));
	else if (strncmp(p, "max bits per frame", len) == 0)
		_maxBitsPerFrame = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax multiplier", len) == 0)
		_iPictureDMaxMultiplier = (int)(atoi(v));
	else if (strncmp(p, "ipicture dmax fraction", len) == 0)
		_iPictureDMaxFraction = (int)(atoi(v));
	else if (strncmp(p, "rate overshoot percent", len) == 0)
		_rateOvershootPercent = (int)(atoi(v));
  else if (strncmp(p, "enable roi encoding", len) == 0)
    _enableROIEncoding = (int)(atoi(v));
  else
	{
		_errorStr = "[H264v2Codec::SetParameter] Write parameter not supported";
		return(0);
	}//end else...

	return(1);
}//end SetParameter.

/**
-----------------------------------------------------------------------
  Member interface functions.
-----------------------------------------------------------------------
*/
void* H264v2Codec::GetMember(const char* type, int* length)
{
	char*	p = (char *)type;
	int		len = (int)strlen(p);
	void* pRet = NULL;
	*length = 0;

	if (strncmp(p, "macroblocks", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_pMb;
	}
	else if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
		*length = _mbLength;
		pRet = (void *)_autoIFrameIncluded;
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    *length = _mbLength;
    pRet = (void *)_roiMultiplier;
  }
  else if (strncmp(p, "reference", len) == 0)
	{
		*length = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		pRet = (void *)_pRLum;
	}
	else if (strncmp(p, "currseqparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_seqParam[_currSeqParam]));
	}
	else if (strncmp(p, "currpicparamset", len) == 0)
	{
		*length = 1;
		pRet = (void *)(&(_picParam[_currPicParam]));
	}
	else if (strncmp(p, "members", len) == 0)
	{
		int numMembers = (int)MEMBER_LEN;
		*length = 1;
		pRet = (void *)(numMembers);	///< Note that MEMBER_LEN is converted to a pointer type.
	}//end else if members...
	else
		_errorStr = "[H264v2Codec::GetMember] Read member not supported";

	return(pRet);
}//end GetMember.

void H264v2Codec::GetMemberName(int ordinal, const char** name, int* length)
{

	if ((ordinal < 0) || (ordinal >= MEMBER_LEN))
		return;
	*name = (const char *)MEMBER_LIST[ordinal];
	*length = (int)strlen(MEMBER_LIST[ordinal]);

}//end GetMemberName.

int H264v2Codec::SetMember(const char* type, void* pValue)
{
	int	 i;
	char *p = (char *)type;
	int  len = (int)strlen(p);

	if (strncmp(p, "autoiframedetectflag", len) == 0)
	{
    if (_autoIFrameIncluded == NULL) return(1);  ///< Do nothing.

    bool* pV = (bool *)pValue;
		for (i = 0; i < _mbLength; i++)
			_autoIFrameIncluded[i] = pV[i];
	}
  else if (strncmp(p, "roi multiplier", len) == 0)
  {
    if (_roiMultiplier == NULL)
    {
      _errorStr = "[H264v2Codec::SetMember] Region of interest array not active";
      return(0);
    }//end !_roiMultiplier...

    double* pV = (double *)pValue;
    for (i = 0; i < _mbLength; i++)
      _roiMultiplier[i] = pV[i];
  }
  else
	{
		_errorStr = "[H264v2Codec::SetMember] Write member not supported";
		return(0);
	}//end else...

	return(1);
}//end SetMember.

/**
-----------------------------------------------------------------------
  Public Implementation.
-----------------------------------------------------------------------
*/
/** Open the codec for encoding/decoding.
The state of the codec and memory allocations are made in this method and are
entirely dependent on the codec parameters. Using SetParameter() all parmeters
must be set prior to calling this methods.
@return : 1 = success, 0 = failure.
*/
int H264v2Codec::Open(void)
{
	int i;

	/// If already open then close first before continuing.
	if (_codecIsOpen)
		Close();

	/// --------------- Configure Sequence & Picture parameter sets -----------------
	/// The _genParamSetOnOpen parameter determines whether or not the seq/pic params 
	/// are generated and set in this call to Open(). If the param sets are to be generated 
	/// then the SetParameters() method calls must have set the appropriate codec params 
	/// prior to calling Open()as these settings are dependent on the codec parameters.
	/// If the param sets are not to be generated then the codec params must be extracted
	/// from the seq/pic param sets.
	if (_genParamSetOnOpen)
	{
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set sequence parameter set";
			Close();
			return(0);
		}//end if !SetSeqParamSet...

		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::Open] Cannot set picture parameter set";
			Close();
			return(0);
		}//end if !SetPicParamSet...
	}//end if _genParamSetOnOpen...
	else
	{
		if (!GetCodecParams(_currPicParam))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !GetCodecParams...
	}//end else...

	/// --------------- Create encoded SPS and PPS streams ----------------------------------------
  /// Every I-Pic will have an SPS NAL, PPS NAL and an IDR NAL concatenated together in a single 
  /// stream. Create a cached param set for the current selection to use in the Code() method.
	if (_prependParamSetsToIPic)
	{
		int tempPicCodingType = _pictureCodingType;

		_pictureCodingType = H264V2_SEQ_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncSeqParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encSeqParamByteLen = GetCompressedByteLength();

		_pictureCodingType = H264V2_PIC_PARAM;
		if (!CodeNonPicNALTypes((void *)_pEncPicParam, H264V2_ENC_PARAM_LEN * 8))
		{
			/// Error string is set in the method.
			Close();
			return(0);
		}//end if !CodeNonPicNALTypes...
		_encPicParamByteLen = GetCompressedByteLength();

		/// Restore state.
		_pictureCodingType = tempPicCodingType;

	}//end if _prependParamSetsToIPic...

	  /// --------------- Alloc image memory ----------------------------------------------
	/// Create an image memory space.
	_lumWidth = _width;
	_lumHeight = _height;
	_chrWidth = _width / 2;
	_chrHeight = _height / 2;

	/// Alloc a large contiguous block with Lum first followed by ChrU then ChrV
	/// for both image blocks of input and reference.
	int lumSize = _lumWidth * _lumHeight;
	int chrSize = _chrWidth * _chrHeight;
	int imgSize = lumSize + 2 * chrSize;
	/// In/Out and ref images with primary lum at the head.
	_pLum = new short[2 * imgSize];
	if (!_pLum)
	{
		_errorStr = "[H264Codec::Open] Image memory unavailable";
		Close();
		return(0);
	}//end if !_pLum...
	  /// Place each image and colour component head pointer.
	_pChrU = &(_pLum[lumSize]);												///< End of _pLum.
	_pChrV = &(_pLum[lumSize + chrSize]);							///< End of _pChrU.
	_pRLum = &(_pLum[imgSize]);												///< End of input image.
	_pRChrU = &(_pLum[imgSize + lumSize]);							///< End of image and _pRLum.
	_pRChrV = &(_pLum[imgSize + lumSize + chrSize]);		///< End of _pRChrU.

  /// Zero the reference and the previous input image spaces. Note that the mem
	/// is contiguous.
	memset((void *)_pLum, 0, 2 * imgSize * sizeof(short));

	/// --------------- Configure the overlays to the img mem -------------------------
	/// The encoding/decoding of the residual image is performed on 4x4 blocks within
	/// each macroblock of the in/out and ref images.
	_Lum = new OverlayMem2Dv2(_pLum, _lumWidth, _lumHeight, 16, 16);
	_RefLum = new OverlayMem2Dv2(_pRLum, _lumWidth, _lumHeight, 16, 16);
	_Cb = new OverlayMem2Dv2(_pChrU, _chrWidth, _chrHeight, 8, 8);
	_RefCb = new OverlayMem2Dv2(_pRChrU, _chrWidth, _chrHeight, 8, 8);
	_Cr = new OverlayMem2Dv2(_pChrV, _chrWidth, _chrHeight, 8, 8);
	_RefCr = new OverlayMem2Dv2(_pRChrV, _chrWidth, _chrHeight, 8, 8);
	if ((_Lum == NULL) || (_RefLum == NULL) || (_Cb == NULL) ||
		(_RefCb == NULL) || (_Cr == NULL) || (_RefCr == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image and reference overlay objects";
		Close();
		return(0);
	}//end if !_Lum...

	  /// --------------- Alloc and configure prediction mem data objects ---------------------
	_p16x16 = new short[256];	///< 16x16 block for predicition operations.
	_16x16 = new OverlayMem2Dv2(_p16x16, 16, 16, 16, 16);
	_p8x8_0 = new short[64];	///< 8x8 blocks for predicition operations.
	_8x8_0 = new OverlayMem2Dv2(_p8x8_0, 8, 8, 8, 8);
	_p8x8_1 = new short[64];
	_8x8_1 = new OverlayMem2Dv2(_p8x8_1, 8, 8, 8, 8);

	if ((_p16x16 == NULL) || (_16x16 == NULL) ||
		(_p8x8_0 == NULL) || (_8x8_0 == NULL) ||
		(_p8x8_1 == NULL) || (_8x8_1 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot create prediction memory objects";
		Close();
		return(0);
	}//end if !_p16x16...

	/// ---------------- Configure Macroblock cache objects -----------------------------
	_mbImg = new H264MbImgCache();
	if (_mbImg == NULL)
	{
		_errorStr = "[H264Codec::Open] Cannot create macroblock image cache object";
		Close();
		return(0);
	}//end if !_mbImg...
	_mbImg->Create();

	/// --------------- Configure Macroblock data objects -----------------------------
	int mbWidth = _lumWidth / 16;		///< Note: Assuming mod 16 image dimensions (potential problem).
	int mbHeight = _lumHeight / 16;
	_mbLength = mbWidth * mbHeight;

	_pMb = new MacroBlockH264[_mbLength];
	_Mb = new MacroBlockH264*[mbHeight];	///< Address array.

	/// Only specified macroblocks are included in the detection of an I-frame. This
	/// flag list is used to indicate that inclusion.
	_autoIFrameIncluded = new bool[_mbLength];

	if ((_pMb == NULL) || (_Mb == NULL) || (_autoIFrameIncluded == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate macroblock data objects";
		Close();
		return(0);
	}//end if !_pMB...

	for (i = 0; i < mbHeight; i++)	///< Load the address array.
		_Mb[i] = &(_pMb[i * mbWidth]);

	/// Load the macroblock image mem 2-D offsets, indices and neighbourhood variables. There
	/// is only one slice (slice num = 0) and therefore extends from macroblock index 0..._mbLength-1.
	MacroBlockH264::Initialise(mbHeight, mbWidth, 0, _mbLength - 1, 0, _Mb);

	/// Load the flag for each macroblock that includes/excludes it from the 
	/// auto I-frame test during motion estimation. Default to include all.
	for (i = 0; i < _mbLength; i++)
		_autoIFrameIncluded[i] = 1;

	/// --------------- Configure colour converters ---------------------------------
	if (_inColour == H264V2_RGB24)
	{
		/// Encoder input.
#ifdef _CCIR601
		_pInColourConverter = new ConvRGB24toYUV420CCIR601V16Real(_width, _height);
#else
		_pInColourConverter = new ConvRGB24toYUV420v16FixP(_width, _height);
#endif

		if (_pInColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate input colour converter";
			Close();
			return(0);
		}//end if !_pInColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pInColourConverter->SetFlip(_flip);
	}//end if _inColour...

	if (_outColour == H264V2_RGB24)
	{
		/// Decoder output.
#ifdef _CCIR601
			_pOutColourConverter = new RealYUV420toRGB24CCIR601ConverterVer16(_width, _height);
#else
			_pOutColourConverter = new ConvYUV420_16toBGR24(_width, _height);	//, 128
#endif

		if (_pOutColourConverter == NULL)
		{
			_errorStr = "[H264Codec::Open] Cannot instantiate output colour converter";
			Close();
			return(0);
		}//end if !_pOutColourConverter...

	/// the calling code is responsible for the flipping of the image
		_pOutColourConverter->SetFlip(_flip);

	}//end if _outColour...

	  /// --------------- Instantiate IT filters ------------------------------------
	  /// Create Integer Transformers (IT) and their inverses for AC and DC coeffs. The
	  /// quantisers are included in the IT transform classes.
	_pF4x4TLum = new FastForward4x4ITImpl2();
	_pF4x4TChr = new FastForward4x4ITImpl2();
	_pFDC4x4T = new FastForwardDC4x4ITImpl1();
	_pFDC2x2T = new FastForwardDC2x2ITImpl1();
	_pI4x4TLum = new FastInverse4x4ITImpl1();
	_pI4x4TChr = new FastInverse4x4ITImpl1();
	_pIDC4x4T = new FastInverseDC4x4ITImpl1();
	_pIDC2x2T = new FastInverseDC2x2ITImpl1();

	if ((_pF4x4TLum == NULL) || (_pF4x4TChr == NULL) || (_pFDC4x4T == NULL) || (_pFDC2x2T == NULL) ||
		(_pI4x4TLum == NULL) || (_pI4x4TChr == NULL) || (_pIDC4x4T == NULL) || (_pIDC2x2T == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Integer Transform filter objects";
		Close();
		return(0);
	}//end if !_pF4x4TLum...

	  /// Set default modes and added scaling for IT filters.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	_pFDC2x2T->SetMode(IForwardTransform::TransformAndQuant);
	_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
	_pIDC4x4T->SetMode(IInverseTransform::TransformAndQuant);
	_pIDC2x2T->SetMode(IInverseTransform::TransformAndQuant);

	// --------------- Create the Vlc encoders and decoders --------------------------
	/// Create the vlc encoders and decoders for use with CAVLC.
	_pPrefixVlcEnc = new PrefixH264VlcEncoderImpl1();
	_pPrefixVlcDec = new PrefixH264VlcDecoderImpl1();
	_pCoeffTokenVlcEnc = new CoeffTokenH264VlcEncoder();
	_pCoeffTokenVlcDec = new CoeffTokenH264VlcDecoder();
	_pTotalZeros4x4VlcEnc = new TotalZeros4x4H264VlcEncoder();
	_pTotalZeros4x4VlcDec = new TotalZeros4x4H264VlcDecoder();
	_pTotalZeros2x2VlcEnc = new TotalZeros2x2H264VlcEncoder();
	_pTotalZeros2x2VlcDec = new TotalZeros2x2H264VlcDecoder();
	_pRunBeforeVlcEnc = new RunBeforeH264VlcEncoder();
	_pRunBeforeVlcDec = new RunBeforeH264VlcDecoder();

	/// Vlc encoder and decoder for the coded block pattern.
	_pBlkPattVlcEnc = new CodedBlkPatternH264VlcEncoder();
	_pBlkPattVlcDec = new CodedBlkPatternH264VlcDecoder();

	/// Vlc encoder and decoder for the delta QP.
	_pDeltaQPVlcEnc = new ExpGolombSignedVlcEncoder();
	_pDeltaQPVlcDec = new ExpGolombSignedVlcDecoder();

	/// Vlc encoder and decoder for the macroblock type.
	_pMbTypeVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pMbTypeVlcDec = new ExpGolombUnsignedVlcDecoder();

	/// Vlc encoder and decoder for intra chr pred mode. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbIChrPredModeVlcEnc = _pMbTypeVlcEnc;
	_pMbIChrPredModeVlcDec = _pMbTypeVlcDec;

	/// Vlc encoder and decoder for motion vector differences. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pMbMotionVecDiffVlcEnc = _pDeltaQPVlcEnc;
	_pMbMotionVecDiffVlcDec = _pDeltaQPVlcDec;

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = _pMbTypeVlcEnc;
	_pHeaderUnsignedVlcDec = _pMbTypeVlcDec;
	_pHeaderSignedVlcEnc = _pDeltaQPVlcEnc;
	_pHeaderSignedVlcDec = _pDeltaQPVlcDec;

	if ((_pPrefixVlcEnc == NULL) || (_pPrefixVlcDec == NULL) ||
		(_pCoeffTokenVlcEnc == NULL) || (_pCoeffTokenVlcDec == NULL) ||
		(_pTotalZeros4x4VlcEnc == NULL) || (_pTotalZeros4x4VlcDec == NULL) ||
		(_pTotalZeros2x2VlcEnc == NULL) || (_pTotalZeros2x2VlcDec == NULL) ||
		(_pRunBeforeVlcEnc == NULL) || (_pRunBeforeVlcDec == NULL) ||
		(_pBlkPattVlcEnc == NULL) || (_pBlkPattVlcDec == NULL) ||
		(_pDeltaQPVlcEnc == NULL) || (_pDeltaQPVlcDec == NULL) ||
		(_pMbTypeVlcEnc == NULL) || (_pMbTypeVlcDec == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate Vlc codec objects";
		Close();
		return(0);
	}//end if !_pPrefixVlcEnc...

	  /// Create a CAVLC encoder and decoder for each coeff block size.
	_pCAVLC4x4 = new CAVLCH264Impl();
	_pCAVLC2x2 = new CAVLCH264Impl();
	if ((_pCAVLC4x4 == NULL) || (_pCAVLC2x2 == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate CAVLC codec objects";
		Close();
		return(0);
	}//end if !_pCAVLC4x4...

	  /// Attach the vlc encoders and decoders to the associated CAVLC.
	_pCAVLC4x4->SetMode(CAVLCH264Impl::Mode4x4);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcEncoder(_pTotalZeros4x4VlcEnc);
	((CAVLCH264Impl *)_pCAVLC4x4)->SetTotalZerosVlcDecoder(_pTotalZeros4x4VlcDec);

	_pCAVLC2x2->SetMode(CAVLCH264Impl::Mode2x2);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcEncoder(_pCoeffTokenVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTokenCoeffVlcDecoder(_pCoeffTokenVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcEncoder(_pPrefixVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetPrefixVlcDecoder(_pPrefixVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcEncoder(_pRunBeforeVlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetRunBeforeVlcDecoder(_pRunBeforeVlcDec);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcEncoder(_pTotalZeros2x2VlcEnc);
	((CAVLCH264Impl *)_pCAVLC2x2)->SetTotalZerosVlcDecoder(_pTotalZeros2x2VlcDec);

	// --------------- Configure bit stream access -----------------------------------
	_pBitStreamWriter = new BitStreamWriterMSB();
	_pBitStreamReader = new BitStreamReaderMSB();
	if ((_pBitStreamWriter == NULL) || (_pBitStreamReader == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate bit stream access objects";
		Close();
		return(0);
	}//end if !_pBitStreamWriter...

	  /// --------------- Configure motion estimators -----------------------------------

	/// Create a motion vector predictor for the motion estimator to use in biasing towards
	/// the predicted vector when distortion choise is ambiguous.
	_pMotionPredictor = new H264MotionVectorPredictorImpl1(_pMb);
	if (!_pMotionPredictor)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector predictor object";
		Close();
		return(0);
	}//end if !_pMotionPredictor...

	  /// Select an appropriate motion estimator.
	int motionVectorRange;	///< In 1/4 pel units but also required for motion compensator in full pel units.
	if ((_width <= 1408) && (_height <= 1152))
		motionVectorRange = 512;	///< [-128.00 ... 127.75]
	else
		motionVectorRange = 1024;	///< [-256.00 ... 255.75]

	/// Fast less accurate estimator.
	//_pMotionEstimator = new MotionEstimatorH264ImplMultiresCrossVer2( (const void *)_pLum,	///< Multi res estimation.
	//	                                                                (const void *)_pRLum,
	//	                                                                _lumWidth,
	//	                                                                _lumHeight,
	//	                                                                motionVectorRange, ///< In 1/4 pel units.
	//	                                                                _pMotionPredictor,
	//	                                                                _autoIFrameIncluded);

	//	_pMotionEstimator = new MotionEstimatorH264ImplMultiresCross(	(const void *)_pLum,	///< Multi res estimation.
	//																																(const void *)_pRLum,
	//																																_lumWidth,
	//																																_lumHeight,
	//																																motionVectorRange, ///< In 1/4 pel units.
	//																																_autoIFrameIncluded);

  /// Cross search algorithm with partial sums as defined in the std reference implementations of H264
  _pMotionEstimator = new MotionEstimatorH264ImplCross( (const void *)_pLum,
                                                        (const void *)_pRLum,
                                                        _lumWidth,
                                                        _lumHeight,
                                                        motionVectorRange, ///< In 1/4 pel units.
                                                        _pMotionPredictor,
                                                        _autoIFrameIncluded);

  /// Slow more accurate multiresolution estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplMultires((const void *)_pLum,	///< Multi res estimation.
	//																													(const void *)_pRLum,
	//																													_lumWidth,
	//																													_lumHeight,
	//																													motionVectorRange, ///< In 1/4 pel units
	//																													_autoIFrameIncluded);

		/// Slowest full accurate estimator.
	//	_pMotionEstimator = new MotionEstimatorH264ImplFull(	(const void *)_pLum,
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

		/// Test motion estimator for collecting data. Full pel only full search based estimation.
	//	_pMotionEstimator = new MotionEstimatorH264ImplTest(	(const void *)_pLum,	///< Multi res estimation.
	//																												(const void *)_pRLum,
	//																												_lumWidth,
	//																												_lumHeight,
	//																												motionVectorRange, ///< In 1/4 pel units.
	//                                                        _pMotionPredictor,
	//																												_autoIFrameIncluded);

	if (_pMotionEstimator != NULL)
	{
		/// Implementation specific modes.
		_pMotionEstimator->SetMode(0);	///< Auto mode.

		//_motionFactor = 2;	///< Abs diff algorithm.
		_motionFactor = 4;	///< Sqr err algorithm.

		if (!_pMotionEstimator->Create())
		{
			_errorStr = "[H264Codec::Open] Cannot create motion estimator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionEstimator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion estimator object";
		Close();
		return(0);
	}//end if else...

	  /// --------------- Configure motion compensator -----------------------------------
	  /// The motion compensator requires the range param to be in full pel units.	
	_pMotionCompensator = new MotionCompensatorH264ImplStd(motionVectorRange / 4);

	if (_pMotionCompensator != NULL)
	{
		if (!_pMotionCompensator->Create((void *)_pRLum, _lumWidth, _lumHeight, 16, 16))
		{
			_errorStr = "[H264Codec::Open] Cannot create motion compensator";
			Close();
			return(0);
		}//end if !Create...
	}//end if _pMotionCompensator...
	else
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate motion compensator object";
		Close();
		return(0);
	}//end if else...

	  /// Create a motion vector list to hold the decoded vectors for the compensation process.
	_pMotionVectors = new VectorStructList(VectorStructList::SIMPLE2D);
	if (!_pMotionVectors)
	{
		_errorStr = "[H264Codec::Open] Cannot create motion vector list object";
		Close();
		return(0);
	}//end if !_pMotionVectors...
	if (!_pMotionVectors->SetLength(mbWidth * mbHeight)) ///< One per Mb for 16x16 vectors only.
	{
		_errorStr = "[H264Codec::Open] Insufficient mem for motion vector list";
		Close();
		return(0);
	}//end if !SetLength...

	  /// --------------- Create image plane encoders and decoders ----------------------
	  /// Select an Intra Decoder.
	_pIntraImgPlaneDecoder = new IntraImgPlaneDecoderImplStdVer1(this);
	/// Set the Inter decoder.
	_pInterImgPlaneDecoder = new InterImgPlaneDecoderImplStdVer1(this);

	/// Select an Intra and Inter Encoder depending on the mode.
	if (_modeOfOperation == H264V2_OPEN)
	{
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplStdVer1(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplStdVer1(this);
	}//end if _modeOfOperation...
	else if (_modeOfOperation == H264V2_MB_QP_MINMAX_ADAPTIVE)
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplMinMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplMinMax(this);
	}//end else...
	else	///< if((_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)||(_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE))
	{
		_pQuant = 26; ///< Start in the middle before adaptation of each mb QP value.
		_pIntraImgPlaneEncoder = new IntraImgPlaneEncoderImplDMax(this);
		_pInterImgPlaneEncoder = new InterImgPlaneEncoderImplDMax(this);

		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			switch (_rateControlModelType)
			{
			case H264V2_RATE_CONTROL_MODEL_QUAD:
				_pRateCntlIFrames = new RateControlImplQuad(40.0, 20000.0);
				_pRateCntlPFrames = new RateControlImplQuad(40.0, 20000.0);
				break;
			case H264V2_RATE_CONTROL_MODEL_POW:
				_pRateCntlIFrames = new RateControlImplPow(65.0, -0.9);
				_pRateCntlPFrames = new RateControlImplPow(15000.0, -1.3);
				break;
			case H264V2_RATE_CONTROL_MODEL_LOG:
				_pRateCntlIFrames = new RateControlImplLog(0.1, 1.2);
				_pRateCntlPFrames = new RateControlImplLog(0.2, 1.4);
				break;
      /*
			case H264V2_RATE_CONTROL_MODEL_MULTI:
			  {
				  double modelParam[RateControlImplMultiModel::MODELS][2];  ///< Initial a and b model parameter per model.
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 65.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -0.9;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.1;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.2;
				  _pRateCntlIFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
				  modelParam[RateControlImplMultiModel::QUAD][0] = 40.0;
				  modelParam[RateControlImplMultiModel::QUAD][1] = 20000.0;
				  modelParam[RateControlImplMultiModel::POW][0] = 15000.0;
				  modelParam[RateControlImplMultiModel::POW][1] = -1.3;
				  modelParam[RateControlImplMultiModel::LOG][0] = 0.2;
				  modelParam[RateControlImplMultiModel::LOG][1] = 1.4;
				  _pRateCntlPFrames = new RateControlImplMultiModel(modelParam, RateControlImplMultiModel::MODELS);
			  }
			break;
      */
			}//end switch _rateControlModelType...

			if ((_pRateCntlPFrames != NULL) && (_pRateCntlIFrames != NULL))
			{
				if ((!_pRateCntlPFrames->Create(_numRateCntlFrames)) || (!_pRateCntlIFrames->Create(_numRateCntlFrames)))
				{
					_errorStr = "[H264Codec::Open] Cannot create rate controllers";
					Close();
					return(0);
				}//end if !Create...
				switch (_rateControlModelType)
				{
				case H264V2_RATE_CONTROL_MODEL_QUAD:
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);  ///< Quad Abs Diff limits.
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 4000000.0, 32.0);
					break;
				case H264V2_RATE_CONTROL_MODEL_POW:
				case H264V2_RATE_CONTROL_MODEL_LOG:
				/*case H264V2_RATE_CONTROL_MODEL_MULTI:*/
					_pRateCntlIFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);  ///< Multi-model Sqr Diff limits
					_pRateCntlPFrames->SetRDLimits(24.0, 0.0001, 67108864.0, 256.0);
					break;
				}//end switch _rateControlModelType...
			}//end if _pRateCntlPFrames...
			else
			{
				_errorStr = "[H264Codec::Open] Cannot instantiate rate controllers";
				Close();
				return(0);
			}//end else...
		}//end if _modeOfOperation...
	}//end else...

	if ((_pIntraImgPlaneEncoder == NULL) || (_pIntraImgPlaneDecoder == NULL) ||
		(_pInterImgPlaneEncoder == NULL) || (_pInterImgPlaneDecoder == NULL))
	{
		_errorStr = "[H264Codec::Open] Cannot instantiate image plane encoder and decoder objects";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...
	if ((!_pIntraImgPlaneEncoder->Create(_mbLength)) ||
		(!_pInterImgPlaneEncoder->Create(_mbLength)))
	{
		_errorStr = "[H264Codec::Open] Cannot create image plane encoders";
		Close();
		return(0);
	}//end if !_pIntraImgPlaneEncoder...

   /// --------------- Create Region of Interest members ----------------------
  _roiMultiplier = new double[_mbLength];
  if(_roiMultiplier == NULL)
  {
    _errorStr = "[H264Codec::Open] Cannot create region of interest members";
    Close();
    return(0);
  }//end if !_roiMultiplier...

   /// Fill it with 1.0 to have no effect on the distortion.
  for (i = 0; i < _mbLength; i++)
    _roiMultiplier[i] = 1.0;

  /// ---------------- Start at the beginning ----------------------------------
	_lastPicCodingType = H264V2_INTRA;
	_prevMotionDistortion = -1;
	_maxFrameNum = 1 << (_seqParam[_currSeqParam]._log2_max_frame_num_minus4 + 4);	///< Max limit (modulus) for _frameNum.
	_idrFrameNum = 0;	///< The starting I-frame counter that must then be different for every contiguous I-frame.
	Restart();

	/// Set up the optimisation time limit timer. If it does not exist then force the parameter to zero.
	if (!SetCounter())
		_timeLimitMs = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/*
	  BlockH264* pB1 = new BlockH264(4, 4);
	  BlockH264* pB2 = new BlockH264(4, 4);
	  short* pB1Mem = pB1->GetBlk();

	  /// Fill with random numbers between -250..250.
	//  srand( 34594938 );
	  srand( 2439967 );
	  for (i = 0; i < 16; i++ )
	  {
		int u = (double)rand() / (RAND_MAX + 1) * (250 - (-250))
			  + (-250);
		pB1Mem[i] = short(u);
	  }//end for i...
	  pB2->CopyBlock(pB1);  ///< Hold a copy to compare with.
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/InputBlk.csv", "Input Blk");

	  /// Forward DCT QP=1
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	  _pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTBlk.csv", "DCT Blk");
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP1Blk.csv", "DCT QP1 Blk");

	  /// Inverse DCT QP=1
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 1);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP1Blk.csv", "IQP1 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP1Blk.csv", "Output QP1 Blk");

	  /// Reload input.
	  pB1->CopyBlock(pB2);
	  /// Forward DCT QP=40
	  _pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 40);
	  pB1->ForwardTransform(_pF4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DCTQP40Blk.csv", "DCT QP40 Blk");

	  /// Inverse DCT QP=40
	  _pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, 40);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/IQP40Blk.csv", "IQP40 Blk");
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
	  pB1->InverseTransform(_pI4x4TLum);
	  DumpBlock(pB1->GetBlkOverlay(), "c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/OutputQP40Blk.csv", "Output QP40 Blk");

	  delete pB2;
	  delete pB1;
	*/
	////////////////////////////////////////////////////////////////////////////////////////////////////

	_errorStr = "[H264Codec::Open] No Erorr";
	_codecIsOpen = 1;
	return(1);
}//end Open.

/** Encode one frame of pels to a compressed stream.
The input source pels in the format specified by "incolour" parameter are compressed
to the output stream. The codeParameter specifies either the max size in bits of the
pCmp buffer or the number of bits to target during the compression process. The interpretation
is determined by the "mode of operation" parameter. For SPS and PPS encoding the input
pSrc is ignored.
@param  pSrc          : Input raw pels of one complete frame.
@param  pCmp          : Output compressed stream buffer.
@param  codeParameter : Mode of operation based bit size limits.
@return               : 1 = success, 0 = failure.
*/
int	H264v2Codec::Code(void* pSrc, void* pCmp, int codeParameter)
{
	int allowedBits, bitsUsed;

	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
		return(CodeNonPicNALTypes(pCmp, codeParameter));

	if (!_codecIsOpen)
	{
		_errorStr = "[H264V2Codec::Code] Codec is not open";
		return(0);
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Code] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Mark the start time of the encoding process.
	if (_timeLimitMs)
		_startTime = (int)GetCounter();
#ifdef H264V2_DUMP_TIMING
	_startTime = (int)GetCounter();
#endif

	/// Interpret the code parameter as a frame bit limit or avg bit rate.
	int frameBitLimit = codeParameter;
	_avgBitsPerFrame = codeParameter;
	double avgBppRate = (double)(_avgBitsPerFrame) / (double)(_lumWidth*_lumHeight);  ///< Bit rate in bits per pel.
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		frameBitLimit = _maxBitsPerFrame; ///< Bit limit must be made sufficiently large for variations in the buffered rate per frame.

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	_bitStreamSize = 0;

	/// Reset the stream writer with the frame bit limit. 
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Only IDR and P pictures are supported.
	if ((_pictureCodingType != H264V2_INTRA) && (_pictureCodingType != H264V2_INTER))
	{
		_errorStr = "[H264v2Codec::Code] Picture coding type not supported";
		return(0);
	}//end if !H264V2_INTRA...

   ///-------------- Colour Space Conversion -----------------------------------------------
  if (_inColour == H264V2_YUV420P16)	      ///< The natural colour space of the encoder with type = short.
		memcpy((void *)_pLum, (const void *)pSrc, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_inColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			_pLum[i] = (short)((unsigned char *)pSrc)[i];
	}//end if H264V2_YUV420P8...
	else
		_pInColourConverter->Convert((void *)pSrc, (void *)_pLum, (void *)_pChrU, (void *)_pChrV);

  ///-------------- Motion Estimation -----------------------------------------------
  /// Motion estimation is used to determine if an IDR frame should be inserted.
	if (_pictureCodingType == H264V2_INTER)
	{
		/// Motion estimation.
		long motionDistortion = 0;

		/// The estimator implementation was chosen in Open() depending on the mode selected.
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
		{
			/// Motion vector lambda adaptation in this mode uses a TCP-like algorithm. Note that it uses the most recent past
      /// P-frame rate control results applied to this P-frame.
			double deltaLambda = 0.0;
			if (_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->UpperDistortionOverflow())
				deltaLambda = MVLAMBDA_MULT*(MVLAMBDA_MAX - _mvLambda);
			else if ((_pRateCntlPFrames->OutOfBounds() && _pRateCntlPFrames->LowerDistortionOverflow()) || (_mvLambda > MVLAMBDA_STEADYSTATE))
				deltaLambda = MVLAMBDA_STEP;
			_mvLambda += deltaLambda;
			if (_mvLambda < 0.0) _mvLambda = 0.0;

			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion, (void *)(&_mvLambda)));
		}//end if H264V2_MB_QP_AVG_ADAPTIVE...
		else
			_pMotionEstimationResult = (VectorStructList *)(_pMotionEstimator->Estimate(&motionDistortion));

		/// The estimation results are processed into an encoded structure list. A 
		/// decision is made on the type of encoding as predictive or basic and 
		/// returns the selection. The _Motion member reflects the choice.

		/// Auto I-picture detection.
		if (_autoIPicture && (_prevMotionDistortion != -1)) ///< Previous frame was not an I-Picture.
		{
			/// Test for an I-picture.
			if (motionDistortion > (_motionFactor * _prevMotionDistortion))
				_pictureCodingType = H264V2_INTRA;
		}///end if _prevMotionDistortion...

		_prevMotionDistortion = motionDistortion;

		/// Force an I-picture if frame counter has wraped around in the modulus calculation.
		if (_frameNum == 0)
			_pictureCodingType = H264V2_INTRA;

	}//end if H264V2_INTER...

	/// The motion estimation process is used to determine if this picture
	/// should rather be coded as an IDR picture. Therefore the INTRA 
	/// picture type coding is done afterwards. 

  ///-------------- Pre-encoding rate control ---------------------------------
  if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
  {
    /// Reset global frame accumulator.
    _frameMSD = 0;
    _frameMAD = 0;
    _frameMAD_N = 0;
    _predFrmMAD = 0.0;

    if (_pictureCodingType == H264V2_INTER)
    {
      /// Distortion is modified only when there is valid data in the rate control model. 
      /// Otherwise it remains at the previous frame's settings.
      if (_pRateCntlPFrames->ValidData())
      {
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlPFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      if (_pRateCntlIFrames->ValidData())
      {
        /// Readjust average frame bits with multiplier.fraction factor.
        avgBppRate = (avgBppRate * (double)_iPictureMultiplier) + ((avgBppRate * (double)_iPictureFraction) / 10.0);
        double upperLimit = avgBppRate*(1.0 + ((double)_rateOvershootPercent / 100.0));
        _dMax = _pRateCntlIFrames->PredictDistortion(avgBppRate, upperLimit);
      }//end if ValidData...
    }//end else if H264V2_INTRA...
  }//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Headers and Preparation  ---------------------------------
  /// For INTRA pictures and before any encoding begins readjust the 
	/// allowable bits based on the I-picture multiplier parameters.
	if (_pictureCodingType == H264V2_INTRA)
	{
		/// Continuously divide by 10 until in the range 0..9.
		while (_iPictureFraction > 10)
			_iPictureFraction = (_iPictureFraction / 10);
		/// Readjust frame bits with multiplier.fraction factor. Protect against excessively large bit limits that result in integer wrapping.
		int prior = frameBitLimit;
		frameBitLimit = (frameBitLimit * _iPictureMultiplier) + ((frameBitLimit * _iPictureFraction) / 10);
		if (frameBitLimit < prior) frameBitLimit = prior;
		_pBitStreamWriter->SetStreamBitSize(frameBitLimit);
		/// New bit limit setting.
		bitLimit = frameBitLimit - 0; ///< Allow some slack for the expected trailing picture bits.
	  /// Reset the frame number for I-pics.
		_frameNum = 0;

		/// Prepend SPS and PPS to the I-picture.
		if (_prependParamSetsToIPic)
		{
			allowedBits = bitLimit - _bitStreamSize;
			int paramTotBitLen = 8 * (_encSeqParamByteLen + _encPicParamByteLen);
			if (allowedBits < paramTotBitLen)
			{
				_errorStr = "[H264V2Codec::Code] Cannot prepend SPS and PPS to I-Picture stream";
				return(0);
			}//end if allowedBits...

			/// Write the pre-encoded SPS to the stream.
			int i;
			for (i = 0; i < _encSeqParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncSeqParam[i]);

			/// Write the pre-encoded PPS to the stream.
			for (i = 0; i < _encPicParamByteLen; i++)  ///< One byte at a time.
				_pBitStreamWriter->Write(8, _pEncPicParam[i]);

			_bitStreamSize += paramTotBitLen;

		}//end if _prependParamSetsToIPic...
	}//end if H264V2_INTRA...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::Code] Cannot write start code to stream";
		return(0);
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Define the NAL unit header based on the seleceted picture coding type. The final NAL type
	/// is only known at this point in the process.
	if (_pictureCodingType == H264V2_INTER)
	{
		_nal._ref_idc = 2;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::NonIDR_NoPartition_Slice;
	}//end if H264V2_INTER...
	else	///< if(_pictureCodingType == H264V2_INTRA)
	{
		_nal._ref_idc = 3;  ///< Non-zero for all referenced frames P and I.
		_nal._unit_type = NalHeaderH264::IDR_Slice;
	}//end else...

	  /// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice header layer with its header flags to
	/// the stream. There is only one slice so the header, macroblocks (slice
	/// data) and tail may be coded in a linear order.
	_slice._frame_num = _frameNum;
	_slice._idr_pic_id = _idrFrameNum;
	/// Force the image plane encoders to use _pQuant as the slice qp and therefore the
	/// slice header is determined before encoding and may be added to the bit stream here.
	_slice._qp = _pQuant;
	_slice._qp_delta = _slice._qp - (_picParam[_currPicParam]._pic_init_qp_minus26 + 26);
	_slice._pic_parameter_set_id = _currPicParam;
	/// Baseline profile only has two slice types and in this implementation they are
	/// used for the entire frame/picture.
	if (_pictureCodingType == H264V2_INTER)
		_slice._type = SliceHeaderH264::P_Slice_All;
	else
		_slice._type = SliceHeaderH264::I_Slice_All;

	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteSliceLayerHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Encode the entire picture. The plane encoders do not write to the stream
	/// but do require to know the available bits. Allowance is made for the single
	/// trailing bit.
	allowedBits = bitLimit - _bitStreamSize - 1;

	///-------------- Encoding process ---------------------------------
	if (_pictureCodingType == H264V2_INTRA)
	{
		_prevMotionDistortion = -1;
		Restart(); ///< Reset the loop for I-picture.

			/// The encoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of slices and their macroblocks.
		if (!_pIntraImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 1))
			return(0);	///< An error has occured.
	}//end if H264V2_INTRA...
	else if (_pictureCodingType == H264V2_INTER)
	{
		/// The encoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneEncoder->Encode(allowedBits, &bitsUsed, 3))
			return(0);	///< An error has occured.
	}//end else H264V2_INTER...

  ///-------------- Write to stream ---------------------------------
	/// Write (concatinate) the macroblock layer (slice data) with its header 
	/// flags to the stream.
	runOutOfBits = WriteSliceDataLayer(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Write (concatinate) the slice trailing bits to the stream. This is a min
  /// of 1 bit + zero bits to the end of the byte boundary.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
		return(0);

	/// Prevent start code emulation within the coded bit stream. The extra byte added
	/// to prevent the emulation is not counted as part of the bit written.
	if (_startCodeEmulationPrevention)
	{
		int offset = 0;
		if ((_pictureCodingType == H264V2_INTRA) && (_prependParamSetsToIPic))
			offset = _encSeqParamByteLen + _encPicParamByteLen;

		_bitStreamSize += InsertEmulationPrevention(_pBitStreamWriter, offset);
	}//end if _startCodeEmulationPrevention...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	///-------------- Post-encoding rate control ---------------------------------
	if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
	{
		/// Measured mean abs and squared difference. Members were set per mb in the ProcessInterMbImplStd() method.
		double frmMAD = (double)(_frameMAD);
		double frmMSD = (double)(_frameMSD);
		if (_frameMAD_N)
		{
			frmMAD = frmMAD / (double)(_frameMAD_N);
			frmMSD = frmMSD / (double)(_frameMAD_N);
		}//end if _frameMAD_N...

		IRateControl* lclRateCntrl = _pRateCntlPFrames; ///< Default to P-Frames.
		if (_pictureCodingType == H264V2_INTER)
		{
			/// Reset the P-Frame RDO model after I-Frames.
	    //if(_lastPicCodingType == H264V2_INTRA)
	    //  _pRateCntlPFrames->Reset();
		}//end if H264V2_INTER...
    else if (_pictureCodingType == H264V2_INTRA)
    {
      /// Force a rest of the mean difference buffer of P-frames to reflect the scene change.
//      _pRateCntlPFrames->Reset(0.0, 0.0, 0.0, frmMSD, frmMAD);

      /// Inform the P-frame rate controller that things will different now that their is probably a new scene sequence.
      _pRateCntlPFrames->SignalSceneChange(frmMSD, frmMAD);  
      lclRateCntrl = _pRateCntlIFrames;
    }//end else if H264V2_INTRA...

		/// Store total rate, coeff rate, distortion, mean difference (and header rate).
		double rateBpp = (double)_bitStreamSize / (double)(_lumWidth*_lumHeight);
    if(_rateControlModelType == H264V2_RATE_CONTROL_MODEL_QUAD)
		  lclRateCntrl->StoreMeasurements(rateBpp, _coeffBitsPerPel, (double)(_dMax), frmMSD, frmMAD);
    else
      lclRateCntrl->StoreMeasurements(rateBpp, rateBpp, (double)(_dMax), frmMSD, frmMAD);

	}//end if H264V2_MB_QP_AVG_ADAPTIVE...

  ///-------------- Prepare for next frame ---------------------------------

	/// Any param changes required for the next picture encoding are done here.
	/// INTER pictures by default follow INTRA pictures.
	int tmpLastPicCodingType = _lastPicCodingType;
	_lastPicCodingType = _pictureCodingType;
	if (_pictureCodingType == H264V2_INTRA)
	{
		_pictureCodingType = H264V2_INTER;
		/// The IDR-frame num is by default 0 unless the previous frame was also an IDR-frame.
		/// In this case, it toggles between 1 and 0. The H.264 standard only requires
		/// consecutive IDR-frames to be different ITU-T Recommendation H.264 (03/2005) page 77.
		if ((tmpLastPicCodingType == H264V2_INTRA) && (_idrFrameNum == 0))
			_idrFrameNum = 1;
		else
			_idrFrameNum = 0;
	}//end if H264V2_INTRA...
	else
		_idrFrameNum = 0;

	///< Increment the frame number relative to the last I-frame for the next frame.
	_frameNum = (_frameNum + 1) % _maxFrameNum;

#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos < _timingTableLen)
	{
		_timingTable.WriteItem(0, _timingTablePos, _timingTablePos);
		_timingTable.WriteItem(1, _timingTablePos, (int)GetCounter() - _startTime);
		_timingTablePos++;
	}//end if _timingTablePos...
#endif

	return(1);
}//end Code.

/** Decode the compresed frame into raw pel samples.
The input types are a compressed picture IDR or P NAL unit, a SPS, a PPS or a concatenated
SPS, PPS and compressed picture. The output is the raw picture pels in the format specified
by the "outcolour" codec parameter.
@param  pCmp      : Compressed stream.
@param  bitLength : Length in bits of pCmp.
@param  pDst      : Raw pel output.
@return           : 1 = success, 0 = failure.
*/
int	H264v2Codec::Decode(void* pCmp, int bitLength, void* pDst)
{
	int	runOutOfBits = 0;
	int frameBitSize = bitLength;
	int bitsUsed = 0;
	int ret = 1;
	int moreNonPicNALUnits = 1;

	/// Set the bit stream access. The bit stream reader and related objects are instantiated within 
	/// Open() and is therefore not available for non-picture NAL types. They are temporarily created 
	/// for these other NAL types.
	_bitStreamSize = bitLength;
	if (!_codecIsOpen)
	{
		_pBitStreamReader = new BitStreamReaderMSB();
		_pHeaderUnsignedVlcDec = new ExpGolombUnsignedVlcDecoder();
		_pHeaderSignedVlcDec = new ExpGolombSignedVlcDecoder();
	}//end if !_codecIsOpen...
		// JFO: function cannot continue when one of 3 pointers is NULL
        if ((_pBitStreamReader == NULL) || (_pHeaderUnsignedVlcDec == NULL) || (_pHeaderSignedVlcDec == NULL))
	{
	  _errorStr = "[H264Codec::Decode] Cannot instantiate stream reader and vlc objects";
	  ret = 0;
	  goto H264V2_D_CLEAN_MEM;
	}//end if !_pBitStreamReader...

	  /// Set the stream reader.
	_pBitStreamReader->SetStream(pCmp, bitLength);

	/// Typically in-band SPS and PPS are prepended to IDR frames. Therefore keep decoding until all
	/// non-picture NAL types are decoded. If the frameBitSize indicates at least 4 more bytes (32 bits)
	/// then we assume there is another NAL to be decoded.
	while (moreNonPicNALUnits)
	{
		/// Extract the start code 0x00000001 from the stream.
		int startCode = _pBitStreamReader->Read(32);
		if (startCode != 1)
		{
			_errorStr = "[H264Codec::Decode] Cannot extract start code from stream";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if frameBitSize...
		frameBitSize -= 32;

		/// Get the NAL header encodings off the bit stream to determine the picture coding type..
		runOutOfBits = ReadNALHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
		frameBitSize -= bitsUsed;
		if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		{
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
		}//end if runOutOfBits...

		/// NAL to coding type conversion.
		switch (_nal._unit_type)
		{
		case NalHeaderH264::IDR_Slice:
			_pictureCodingType = H264V2_INTRA;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::NonIDR_NoPartition_Slice:
			/// Slice without partitioning and therefore only one set of slice parameters and NAL type = Slice type.
			_pictureCodingType = H264V2_INTER;
			moreNonPicNALUnits = 0;
			break;
		case NalHeaderH264::SeqParamSet:
		case NalHeaderH264::PicParamSet:
		{
			int changed = 1;  ///< Indicate if the decoded params for this index have changed. Assume they have changed as the default.
			if (_nal._unit_type == NalHeaderH264::SeqParamSet)
			{
				_pictureCodingType = H264V2_SEQ_PARAM;
				/// Read the seq param set off the stream.
				runOutOfBits = ReadSeqParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currSeqParam, &changed);
			}//end if SeqParamSet...
			else ///< if(_nal._unit_type == NalHeaderH264::PicParamSet)
			{
				_pictureCodingType = H264V2_PIC_PARAM;
				/// Read the pic param set off the stream.
				runOutOfBits = ReadPicParamSet(_pBitStreamReader, frameBitSize, &bitsUsed, &_currPicParam, &changed);
				if (!runOutOfBits)
					_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
			}//end else...
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

			/// Read the trailing bits off the stream.
			runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
			frameBitSize -= bitsUsed;
			if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
			{
				ret = 0;
				goto H264V2_D_CLEAN_MEM;
			}//end if runOutOfBits...

	/// If the codec is in the open state then any change in sequence or picture param set requires the
	/// codec to be restarted with these new sets. But the bit stream must be preserved and restored 
	/// after the call to Open().
			if (_codecIsOpen)
			{
				if (changed)
				{
					/// Preserve the bitstream
					IBitStreamReader* pTmpBitStreamReader = new BitStreamReaderMSB();
					pTmpBitStreamReader->Copy(_pBitStreamReader);

					int tmpPicCodingType = _pictureCodingType; ///< Store the coding type.

					_genParamSetOnOpen = 0; ///< Must be off if the new param sets are to be used.
					if (!Open())
					{
						delete pTmpBitStreamReader;
						ret = 0;
						goto H264V2_D_CLEAN_MEM;
					}//end if !Open...

					/// Restore the picture coding type.
					_pictureCodingType = tmpPicCodingType;
					/// Restore the bitstream.
					_pBitStreamReader->Copy(pTmpBitStreamReader);
					delete pTmpBitStreamReader;
				}//end if changed...

			}//end if _codecIsOpen...

#ifdef H264V2_DUMP_HEADERS
			if (_headerTablePos < _headerTableLen)
			{
				_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
				_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
				_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
				_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
				_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
				_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

				_headerTablePos++;
			}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

			if (frameBitSize < 32) ///< No more units.
			{
				moreNonPicNALUnits = 0;
				if (_codecIsOpen)
					return(1);
				else
				{
					/// Clean up the mem.
					ret = 1;
					goto H264V2_D_CLEAN_MEM;
				}//end else...
			}//end if frameBitSize...

		};//end SeqParamSet and PicParamSet block...
		break;
		default:
			_errorStr = "[H264v2Codec::Decode] NAL unit type not supported";
			ret = 0;
			goto H264V2_D_CLEAN_MEM;
			break;
		}//end switch _unit_type...
	}//end while moreNonPicNALUnits...

	  /// Only IDR and P pictures are decoded from here and the codec must be open.
	if (!_codecIsOpen)
	{
		_errorStr = "[H264v2Codec::Decode] Codec is not open";
		ret = 0;
		goto H264V2_D_CLEAN_MEM;
	}//end if !_codecIsOpen...

	  /// Only baseline profile is supported: _profile_idc = 66.
	if (_seqParam[_currSeqParam]._profile_idc != 66)
	{
		_errorStr = "[H264Codec::Decode] This implementation only supports the baseline profile";
		return(0);
	}//end if _profile_idc not baseline...

  /// Remove prevention of start code emulation codes within the coded bit stream.
	if (_startCodeEmulationPrevention)
		frameBitSize -= RemoveEmulationPrevention(_pBitStreamReader);

	/// Get the slice header encodings off the bit stream. As this implementation 
	/// has only one slice, the slice header, slice data (macroblocks) and the 
	/// slice trailing bits can be decoded in linear order.
	runOutOfBits = ReadSliceLayerHeader(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);
	/// Load frame counter members from the decoded slice header.
	_frameNum = _slice._frame_num;
	_idrFrameNum = _slice._idr_pic_id;
	/// Load the picture and sequence parameter set references.
	_currPicParam = _slice._pic_parameter_set_id;
	_currSeqParam = _picParam[_currPicParam]._seq_parameter_set_id;
	/// There is only one slice so the quant parameter is picture quant + the delta slice quant.
	_slice._qp = _picParam[_currPicParam]._pic_init_qp_minus26 + 26 + _slice._qp_delta;
	_pQuant = _slice._qp;

#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos < _headerTableLen)
	{
		_headerTable.WriteItem(0, _headerTablePos, _nal._unit_type);     /// "NALType"
		_headerTable.WriteItem(1, _headerTablePos, _nal._ref_idc);       /// "NALRefIdc"
		_headerTable.WriteItem(2, _headerTablePos, _slice._idr_pic_id);  ///  "IdrPicId"
		_headerTable.WriteItem(3, _headerTablePos, _slice._frame_num);   ///  "FrmNum"
		_headerTable.WriteItem(4, _headerTablePos, _slice._type);        ///  "SliceType"
		_headerTable.WriteItem(5, _headerTablePos, _slice._qp);          ///  "Qp"

		_headerTablePos++;
	}//end if _headerTablePos...
#endif // H264V2_DUMP_HEADERS

	/// Get the macroblock (slice data) encodings off the bit stream.
	runOutOfBits = ReadSliceDataLayer(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// Get the slice trailing bits off the bit stream. 
	runOutOfBits = ReadTrailingBits(_pBitStreamReader, frameBitSize, &bitsUsed);
	frameBitSize -= bitsUsed;
	if (runOutOfBits > 0) ///< An error has occurred. 1 = run out of bits, 2 = vlc decode error.
		return(0);

	/// INTRA frames require the reference images to be zeroed.
	if (_pictureCodingType == H264V2_INTRA)
	{
		Restart();	///< Reset the loop and ref img.

			/// The decoder was chosen in Open() depending on the mode selected. It
			/// operates on the full list of macroblocks.
		if (!_pIntraImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end if INTRA...
	else
	{
		/// INTER picture decode.
		/// The decoder was chosen in Open() depending on the mode selected. It
		/// operates on the list of macroblocks. Motion compensation is included.
		if (!_pInterImgPlaneDecoder->Decode())
			return(0);	///< An error has occured.
	}//end else INTER...

	/// In-loop filter for 4x4 block boundaries to remove blocking artefacts.
	if (_slice._disable_deblocking_filter_idc != 1)
		ApplyLoopFilter();

	/// Convert to the output image depending on the output dimension settings. Set
	  /// up in the Open() method for the correctly selected converter.
	if (_outColour == H264V2_YUV420P16)      /// The natural colour space of the decoder with type = short.
		memcpy((void *)pDst, (const void *)_pLum, ((_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight)) * sizeof(short));
	else if (_outColour == H264V2_YUV420P8)  ///< ...type = byte.
	{
		int colLen = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
		for (int i = 0; i < colLen; i++)
			((unsigned char *)pDst)[i] = (unsigned char)_pLum[i];
	}//end if H264V2_YUV420P8...
	else
		_pOutColourConverter->Convert(_pRLum, _pRChrU, _pRChrV, pDst);

	return(1);

	/// Clean up memory objects.
H264V2_D_CLEAN_MEM:
	if (_pHeaderUnsignedVlcDec != NULL)
	{
		delete _pHeaderUnsignedVlcDec;
		_pHeaderUnsignedVlcDec = NULL;
	}//end if _pHeaderUnsignedVlcDec...
	if (_pHeaderSignedVlcDec != NULL)
	{
		delete _pHeaderSignedVlcDec;
		_pHeaderSignedVlcDec = NULL;
	}//end if _pHeaderSignedVlcDec...
	if (_pBitStreamReader != NULL)
	{
		delete _pBitStreamReader;
		_pBitStreamReader = NULL;
	}//end if _pBitStreamReader...

	return(ret);
}//end Decode.

int H264v2Codec::Close(void)
{
#ifdef H264V2_DUMP_HEADERS
	if (_headerTablePos > 0)
		_headerTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC10/CodecAnalyser/LoyisoGola_my_enc_qp48_16P.csv", ",", 1);

	_headerTablePos = 0;
#endif // H264V2_DUMP_HEADERS
#ifdef H264V2_DUMP_MB_RD_DATA
	if (_mbRDTablePos > 1)
		_mbRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/QPvRD_Foreman.csv", ",", 1);

	_mbRDTablePos = 1;
#endif
#ifdef H264V2_DUMP_TIMING
	if (_timingTablePos > 0)
		_timingTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/EncodeTimes.csv", ",", 1);

	_timingTablePos = 0;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
	/// Collect frame RD values.
	_frmRDTableLen = _pRateCntlPFrames->GetFameBufferLength();
	_frmRDTable.Create(4, _frmRDTableLen);  /// frame, mb Dmax, rate, MAD.

	_frmRDTable.SetHeading(0, "Frame");
	_frmRDTable.SetDataType(0, MeasurementTable::INT);
	_frmRDTable.SetHeading(1, "Dmax");
	_frmRDTable.SetDataType(1, MeasurementTable::INT);
	_frmRDTable.SetHeading(2, "Rate");
	_frmRDTable.SetDataType(2, MeasurementTable::DOUBLE);
	_frmRDTable.SetHeading(3, "MAD");
	_frmRDTable.SetDataType(3, MeasurementTable::DOUBLE);

	_frmRDTablePos = 0;

	if (_pRateCntlPFrames->ValidData())
	{
		int frmNum = _frmRDTableLen - 1; ///< Frame numbering is in reverse order.
		for (_frmRDTablePos = 0; _frmRDTablePos < _frmRDTableLen; _frmRDTablePos++, frmNum--)
		{
			_frmRDTable.WriteItem(0, _frmRDTablePos, _frmRDTablePos); ///< Frame counter.
			_frmRDTable.WriteItem(1, _frmRDTablePos, (int)(0.5 + (_pRateCntlPFrames->GetDmaxSamples())[frmNum]));
			_frmRDTable.WriteItem(2, _frmRDTablePos, (_pRateCntlPFrames->GetRateSamples())[frmNum]); ///< In bits/pixel
			_frmRDTable.WriteItem(3, _frmRDTablePos, (_pRateCntlPFrames->GetMDSamples())[frmNum]);
		}//end for _frmRDTablePos...

		_frmRDTable.Save("c:/keithf/CppProjects/RTVC/Projects/Win32/VC11/CodecAnalyser/DmaxVsR_Foreman.csv", ",", 1);
		_frmRDTablePos = 0;
	}//end if ValidData...

#endif

	/// Free the image memory and associated overlays.
	if (_Lum != NULL)
		delete _Lum;
	_Lum = NULL;
	if (_Cb != NULL)
		delete _Cb;
	_Cb = NULL;
	if (_Cr != NULL)
		delete _Cr;
	_Cr = NULL;

	if (_RefLum != NULL)
		delete _RefLum;
	_RefLum = NULL;
	if (_RefCb != NULL)
		delete _RefCb;
	_RefCb = NULL;
	if (_RefCr != NULL)
		delete _RefCr;
	_RefCr = NULL;

	if (_pLum != NULL)
		delete[] _pLum;
	_pLum = NULL;
	_pChrU = NULL;
	_pChrV = NULL;
	_pRLum = NULL;
	_pRChrU = NULL;
	_pRChrV = NULL;

	if (_16x16 != NULL)
		delete _16x16;
	_16x16 = NULL;
	if (_p16x16 != NULL)
		delete[] _p16x16;
	_p16x16 = NULL;
	if (_8x8_0 != NULL)
		delete _8x8_0;
	_8x8_0 = NULL;
	if (_p8x8_0 != NULL)
		delete[] _p8x8_0;
	_p8x8_0 = NULL;
	if (_8x8_1 != NULL)
		delete _8x8_1;
	_8x8_1 = NULL;
	if (_p8x8_1 != NULL)
		delete[] _p8x8_1;
	_p8x8_1 = NULL;

	if (_mbImg != NULL)
		delete _mbImg;
	_mbImg = NULL;

	/// Colour converters.
	if (_pInColourConverter != NULL)
		delete _pInColourConverter;
	_pInColourConverter = NULL;

	if (_pOutColourConverter != NULL)
		delete _pOutColourConverter;
	_pOutColourConverter = NULL;

	/// IT transform filters.
	if (_pF4x4TLum != NULL)
		delete _pF4x4TLum;
	_pF4x4TLum = NULL;
	if (_pF4x4TChr != NULL)
		delete _pF4x4TChr;
	_pF4x4TChr = NULL;
	if (_pFDC4x4T != NULL)
		delete _pFDC4x4T;
	_pFDC4x4T = NULL;
	if (_pFDC2x2T != NULL)
		delete _pFDC2x2T;
	_pFDC2x2T = NULL;
	if (_pI4x4TLum != NULL)
		delete _pI4x4TLum;
	_pI4x4TLum = NULL;
	if (_pI4x4TChr != NULL)
		delete _pI4x4TChr;
	_pI4x4TChr = NULL;
	if (_pIDC4x4T != NULL)
		delete _pIDC4x4T;
	_pIDC4x4T = NULL;
	if (_pIDC2x2T != NULL)
		delete _pIDC2x2T;
	_pIDC2x2T = NULL;

	/// Vlc encoders and decoders.
	if (_pPrefixVlcEnc != NULL)
		delete _pPrefixVlcEnc;
	_pPrefixVlcEnc = NULL;
	if (_pPrefixVlcDec != NULL)
		delete _pPrefixVlcDec;
	_pPrefixVlcDec = NULL;

	if (_pCoeffTokenVlcEnc != NULL)
		delete _pCoeffTokenVlcEnc;
	_pCoeffTokenVlcEnc = NULL;
	if (_pCoeffTokenVlcDec != NULL)
		delete _pCoeffTokenVlcDec;
	_pCoeffTokenVlcDec = NULL;

	if (_pTotalZeros4x4VlcEnc != NULL)
		delete _pTotalZeros4x4VlcEnc;
	_pTotalZeros4x4VlcEnc = NULL;
	if (_pTotalZeros4x4VlcDec != NULL)
		delete _pTotalZeros4x4VlcDec;
	_pTotalZeros4x4VlcDec = NULL;

	if (_pTotalZeros2x2VlcEnc != NULL)
		delete _pTotalZeros2x2VlcEnc;
	_pTotalZeros2x2VlcEnc = NULL;
	if (_pTotalZeros2x2VlcDec != NULL)
		delete _pTotalZeros2x2VlcDec;
	_pTotalZeros2x2VlcDec = NULL;

	if (_pRunBeforeVlcEnc != NULL)
		delete _pRunBeforeVlcEnc;
	_pRunBeforeVlcEnc = NULL;
	if (_pRunBeforeVlcDec != NULL)
		delete _pRunBeforeVlcDec;
	_pRunBeforeVlcDec = NULL;

	if (_pBlkPattVlcEnc != NULL)
		delete _pBlkPattVlcEnc;
	_pBlkPattVlcEnc = NULL;
	if (_pBlkPattVlcDec != NULL)
		delete _pBlkPattVlcDec;
	_pBlkPattVlcDec = NULL;

	if (_pDeltaQPVlcEnc != NULL)
		delete _pDeltaQPVlcEnc;
	_pDeltaQPVlcEnc = NULL;
	if (_pDeltaQPVlcDec != NULL)
		delete _pDeltaQPVlcDec;
	_pDeltaQPVlcDec = NULL;

	if (_pMbTypeVlcEnc != NULL)
		delete _pMbTypeVlcEnc;
	_pMbTypeVlcEnc = NULL;
	if (_pMbTypeVlcDec != NULL)
		delete _pMbTypeVlcDec;
	_pMbTypeVlcDec = NULL;

	/// Vlc codecs that were used as references and not instantiated.
	_pMbIChrPredModeVlcEnc = NULL;
	_pMbIChrPredModeVlcDec = NULL;
	_pMbMotionVecDiffVlcEnc = NULL;
	_pMbMotionVecDiffVlcDec = NULL;
	_pHeaderUnsignedVlcEnc = NULL;
	_pHeaderUnsignedVlcDec = NULL;
	_pHeaderSignedVlcEnc = NULL;
	_pHeaderSignedVlcDec = NULL;

	/// The CAVLC codecs.
	if (_pCAVLC4x4 != NULL)
		delete _pCAVLC4x4;
	_pCAVLC4x4 = NULL;
	if (_pCAVLC2x2 != NULL)
		delete _pCAVLC2x2;
	_pCAVLC2x2 = NULL;

	/// Macroblock data objects.
	if (_pMb != NULL)
		delete[] _pMb;
	_pMb = NULL;
	if (_Mb != NULL)
		delete[] _Mb;
	_Mb = NULL;

	if (_autoIFrameIncluded != NULL)
		delete[] _autoIFrameIncluded;
	_autoIFrameIncluded = NULL;

	/// Stream access.
	if (_pBitStreamWriter != NULL)
		delete _pBitStreamWriter;
	_pBitStreamWriter = NULL;

	if (_pBitStreamReader != NULL)
		delete _pBitStreamReader;
	_pBitStreamReader = NULL;

	/// Motion estimator and compensators.
	if (_pMotionEstimator != NULL)
		delete _pMotionEstimator;
	_pMotionEstimator = NULL;

	/// Motion compensation vectors.
	if (_pMotionVectors != NULL)
		delete _pMotionVectors;
	_pMotionVectors = NULL;

	if (_pMotionCompensator != NULL)
		delete _pMotionCompensator;
	_pMotionCompensator = NULL;

	if (_pMotionPredictor != NULL)
		delete _pMotionPredictor;
	_pMotionPredictor = NULL;

	/// Image plane encoders/decoders.
	if (_pIntraImgPlaneEncoder != NULL)
		delete _pIntraImgPlaneEncoder;
	_pIntraImgPlaneEncoder = NULL;

	if (_pInterImgPlaneEncoder != NULL)
		delete _pInterImgPlaneEncoder;
	_pInterImgPlaneEncoder = NULL;

	if (_pIntraImgPlaneDecoder != NULL)
		delete _pIntraImgPlaneDecoder;
	_pIntraImgPlaneDecoder = NULL;

	if (_pInterImgPlaneDecoder != NULL)
		delete _pInterImgPlaneDecoder;
	_pInterImgPlaneDecoder = NULL;

	/// Rate controllers.
	if (_pRateCntlPFrames != NULL)
	{
		_pRateCntlPFrames->Dump(H264V2_RATE_CNTL_PFRAMES);
		//    _pRateCntlPFrames->Dump();
		delete _pRateCntlPFrames;
		_pRateCntlPFrames = NULL;
	}//end if _pRateCntlPFrames...
	if (_pRateCntlIFrames != NULL)
	{
		_pRateCntlIFrames->Dump(H264V2_RATE_CNTL_IFRAMES);
		delete _pRateCntlIFrames;
		_pRateCntlIFrames = NULL;
	}//end if _pRateCntlIFrames...

  /// Region of Interest encoding.
  if (_roiMultiplier != NULL)
    delete[] _roiMultiplier;
  _roiMultiplier = NULL;

	_codecIsOpen = 0;
	return(1);
}//end Close.

void H264v2Codec::Restart(void)
{
	_pictureCodingType = H264V2_INTRA;
	_frameNum = 0;				///< Reset the frame counter.
  /// _idrFrameNum does not require reseting.

  /// Zero the reference image. Note that the colour components are 
	/// held in contiguous mem.
	int imgSize = (_lumWidth * _lumHeight) + 2 * (_chrWidth * _chrHeight);
	memset(_pRLum, 0, imgSize * sizeof(short));

}//end Restart.

/*
-----------------------------------------------------------------------
  Private Implementation.
-----------------------------------------------------------------------
*/
/** Code non-picture nal types.
This method operates independently and therefore all the coding objects must be
instantiated and destroyed before and after the coding process. This is typically an
out-of-band process and therefore speed is not critical. The codec must NOT be open
for calls to this method i.e. _codecIsOpen = 0.
@param pCmp						: The stream memory to write to.
@param frameBitLimit	: The max number of bits to use.
@return								: 1 = success, 0 = failure.
*/
int H264v2Codec::CodeNonPicNALTypes(void* pCmp, int frameBitLimit)
{
	int allowedBits, bitsUsed;

	int runOutOfBits = 0;
	int bitLimit = frameBitLimit;
	int ret = 1;	///< Return value default to success.
	_bitStreamSize = 0;

	/// This method uses the class members and therefore Open() must not be called before
	/// coding non-pic nal-types.
	if (_codecIsOpen)
	{
		_errorStr = "[H264V2::CodeNonPicNALTypes] Codec must not be open for non-picture nal types";
		return(0);
	}//end if _codecIsOpen...

	  /// Check which types are supported with this implementation.
	if ((_pictureCodingType != H264V2_SEQ_PARAM) && (_pictureCodingType != H264V2_PIC_PARAM))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Non-Nal picture type not supported";
		return(0);
	}//end if !H264V2_SEQ_PARAM...

	///----------------------------------------------------------------------------------------------
	/// Instantiate the mem objects required for the encoding.

	/// A stream writer.
	_pBitStreamWriter = new BitStreamWriterMSB();
	if (_pBitStreamWriter == NULL)
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate bit stream writer object";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if !_pBitStreamWriter...
	/// Set the stream writer to the compressed input parameter reference.
	_pBitStreamWriter->SetStream(pCmp, frameBitLimit);

	/// Vlc encoder and decoder for general headers. ExpGolomb codecs
	/// are stateless therefore they can be reused.
	_pHeaderUnsignedVlcEnc = new ExpGolombUnsignedVlcEncoder();
	_pHeaderSignedVlcEnc = new ExpGolombSignedVlcEncoder();
	if ((_pHeaderUnsignedVlcEnc == NULL) || (_pHeaderSignedVlcEnc == NULL))
	{
		_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot instantiate vlc encoder objects";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if _pHeaderUnsignedVlcEnc...

	///----------------------------------------------------------------------------------------------
	/// Parameter set coding. The _currSeqParam and _currPicParam members determine the param sets
	/// to encode. From here the picture coding type is only H264V2_SEQ_PARAM or H264V2_PIC_PARAM.

	_nal._ref_idc = 3;

	if (_pictureCodingType == H264V2_SEQ_PARAM)
	{
		_nal._unit_type = NalHeaderH264::SeqParamSet;
		/// Sequence parameter set for Baseline profile.
		if (!SetSeqParamSet(_currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set sequence parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetSeqParamSet...
	}//end if H264V2_SEQ_PARAM...
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
	{
		_nal._unit_type = NalHeaderH264::PicParamSet;
		/// Picture parameter set.
		if (!SetPicParamSet(_currPicParam, _currSeqParam))
		{
			_errorStr = "[H264Codec::CodeNonPicNALTypes] Cannot set picture parameter set";
			ret = 0;
			goto H264V2_CNPNT_CLEAN_MEM;
		}//end if !SetPicParamSet...
	}//end else...

  /// Write the 32-bit start code 0x00000001 to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (allowedBits < 32)
	{
		_errorStr = "[H264V2Codec::CodeNonPicNALTypes] Cannot write start code to stream";
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if allowedBits...
	_pBitStreamWriter->Write(32, 1);
	_bitStreamSize += 32;

	/// Write the NAL header to the stream. 
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteNALHeader(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write the parameter set to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	if (_pictureCodingType == H264V2_SEQ_PARAM)
		runOutOfBits = WriteSeqParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currSeqParam);
	else ///< if(_pictureCodingType == H264V2_PIC_PARAM)
		runOutOfBits = WritePicParamSet(_pBitStreamWriter, allowedBits, &bitsUsed, _currPicParam);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	/// Write trailing bits to the stream.
	allowedBits = bitLimit - _bitStreamSize;
	runOutOfBits = WriteTrailingBits(_pBitStreamWriter, allowedBits, &bitsUsed);
	_bitStreamSize += bitsUsed;
	if (runOutOfBits) ///< or if(== 2) An error has occured.
	{
		ret = 0;
		goto H264V2_CNPNT_CLEAN_MEM;
	}//end if runOutOfBits...

	///----------------------------------------------------------------------------------------------
	/// Clean up memory objects.
H264V2_CNPNT_CLEAN_MEM:
	if (_pHeaderUnsignedVlcEnc != NULL)
	{
		delete _pHeaderUnsignedVlcEnc;
		_pHeaderUnsignedVlcEnc = NULL;
	}//end if _pHeaderUnsignedVlcEnc...
	if (_pHeaderSignedVlcEnc != NULL)
	{
		delete _pHeaderSignedVlcEnc;
		_pHeaderSignedVlcEnc = NULL;
	}//end if _pHeaderSignedVlcEnc...
	if (_pBitStreamWriter != NULL)
	{
		delete _pBitStreamWriter;
		_pBitStreamWriter = NULL;
	}//end if _pBitStreamWriter...

	return(ret);
}//end CodeNonPicNALTypes.

/** Set the Sequence parameter set.
Set one of the seq param sets defined by the index parameter where the
values are determined by interpreting the codec parameters.
@param index	:	Seq parameter set to modify [0..31].
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetSeqParamSet(int index)
{
	if (index > 31)
		return(0);

	_seqParam[index]._seq_parameter_set_id = index;					///< The index for this definition of sequence params [0..31].
	_seqParam[index]._profile_idc = 66;							///< Baseline profile = 66.
	_seqParam[index]._constraint_set0_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set1_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set2_flag = 0;							///< = 0.
	_seqParam[index]._constraint_set3_flag = 0;							///< = 0.
	_seqParam[index]._level_idc = 20;							///< = 20 (Level num = 2, calculated as 10 x level num).
	_seqParam[index]._chroma_format_idc = 1;							///< Range = [0..3]. When not present = 1 (4:2:0).
	_seqParam[index]._residual_colour_transform_flag = 0;							///< = 0.
	_seqParam[index]._bit_depth_luma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/lum component).
	_seqParam[index]._bit_depth_chroma_minus8 = 0;							///< Range = [0..4]. When not present = 0 (8 bits/chr component).
	_seqParam[index]._qpprime_y_zero_transform_bypass_flag = 0;							///< If QP = 0, this flag indicates bypassing the transform process. When not present = 0.
	_seqParam[index]._seq_scaling_matrix_present_flag = 0;							///< = 0. No scaling matrices for baseline profile. Indicates existence of _seq_scaling_list_present_flag flags.
	/// Not initialised _seq_scaling_list_present_flag[8]			///< if _seq_scaling_matrix_present_flag, these indicate lists not present/present (0/1).
	_seqParam[index]._log2_max_frame_num_minus4 = _seqParamSetLog2MaxFrameNumMinus4;	///< Range = [0..12]. MaxFrameNum = 2^(_log2_max_frame_num_minus4 + 4) for slice _frame_num derivations.
	_seqParam[index]._pic_order_cnt_type = 2;							///< Range = [0..2]. 2 = 1-to-1 mapping. (Picture order count = frame num).
	_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = 0;							///< For B-Slice decoding.  There are no B-Slices in the baseline profile. 
	_seqParam[index]._delta_pic_order_always_zero_flag = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_non_ref_pic = 0;							///< For B-Slice decoding.
	_seqParam[index]._offset_for_top_to_bottom_field = 0;							///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = 0;							///< For B-Slice decoding.
	/// Not initialised _offset_for_ref_frame[256];						///< For B-Slice decoding.
	_seqParam[index]._num_ref_frames = 1;							///< Max num of short-term and long-term ref frames.
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = 0;							///< Indicates allowed values of slice _frame_num.
	_seqParam[index]._frame_mbs_only_flag = 1;							///< = 1 (baseline profile). fields/frames = 0/1.
	_seqParam[index]._mb_adaptive_frame_field_flag = 0;							///< Indicates switching between frame and field macroblocks. When not present = 0.
	_seqParam[index]._direct_8x8_inference_flag = 0;							///< Methods for B-Slice motion vector decoding. There are no B-Slices in the baseline profile.
	_seqParam[index]._frame_cropping_flag = 0;							///< Indicates that the cropping params below follow in the stream.
	_seqParam[index]._frame_crop_left_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_right_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_top_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._frame_crop_bottom_offset = 0;							///< In frame coordinate units.
	_seqParam[index]._vui_parameters_present_flag = 0;							///< vui parameters follow.

	if ((_width < 16) || (_height < 16))
		return(0);

	_seqParam[index]._pic_width_in_mbs_minus1 = (_width / 16) - 1;	///< Width of decoded pic in units of macroblocks. Derive lum and chr pic width from this variable.
	_seqParam[index]._pic_height_in_map_units_minus1 = (_height / 16) - 1;	///< Map units are 2 macroblocks for fields and 1 for frames. Derive lum and chr pic height from this variable.

	return(1);
}//end SetSeqParamSet.

/** Write the sequence parameter set to a bit stream.
The seq param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Sequence parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;

	/// Only baseline profile is supported: _profile_idc = 66.
//	if(_seqParam[index]._profile_idc != 66)
//	{
//		_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 0;
//		return(3);
//	}//end if _profile_idc not baseline...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (allowedBits < 24)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
	{
		bsw->Write(8, _seqParam[index]._profile_idc);						///< u(8)
		bsw->Write(_seqParam[index]._constraint_set0_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set1_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set2_flag);			///< u(1)
		bsw->Write(_seqParam[index]._constraint_set3_flag);			///< u(1)
		bsw->Write(4, 0);																				///< u(4), reserved_zero_4bits.
		bsw->Write(8, _seqParam[index]._level_idc);							///< u(8)
	}//end if bsw...
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._seq_parameter_set_id);  ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._chroma_format_idc);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _residual_colour_transform_flag
		if (_seqParam[index]._chroma_format_idc == 3)
		{
			if (bsw)
				bsw->Write(_seqParam[index]._residual_colour_transform_flag); ///< u(1)
			bitsUsedSoFar++;
		}///end if _chroma_format_idc...

		/// _bit_depth_luma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_luma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _bit_depth_chroma_minus8
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._bit_depth_chroma_minus8);  ///< ue(v)
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// Two flags
		if (bsw)
		{
			bsw->Write(_seqParam[index]._qpprime_y_zero_transform_bypass_flag); ///< u(1)
			bsw->Write(_seqParam[index]._seq_scaling_matrix_present_flag);      ///< u(1)
		}//end if bsw...
		bitsUsedSoFar += 2;

		/// Scaling matricies
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				/// _seq_scaling_list_present_flag[8]
				if (bsw)
					bsw->Write(_seqParam[index]._seq_scaling_list_present_flag[i]); ///< u(1)
				bitsUsedSoFar++;

				bitCount = 0;
				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitCount += WriteSeqParamScalingList(bsw, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
				bitsUsedSoFar += bitCount;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_frame_num_minus4); ///< ue(v)
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_order_cnt_type
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_order_cnt_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._delta_pic_order_always_zero_flag);
		bitsUsedSoFar++;

		/// _offset_for_non_ref_pic
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_non_ref_pic);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _offset_for_top_to_bottom_field
		bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_top_to_bottom_field);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			bitCount = _pHeaderSignedVlcEnc->Encode(_seqParam[index]._offset_for_ref_frame[i]);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_WSPS_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._num_ref_frames);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _gaps_in_frame_num_value_allowed_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._gaps_in_frame_num_value_allowed_flag);
	bitsUsedSoFar++;

	/// _pic_width_in_mbs_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_width_in_mbs_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_height_in_map_units_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._pic_height_in_map_units_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WSPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _frame_mbs_only_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_mbs_only_flag);
	bitsUsedSoFar++;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		if ((bitsUsedSoFar + 1) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(_seqParam[index]._mb_adaptive_frame_field_flag);
		bitsUsedSoFar++;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._direct_8x8_inference_flag);
	bitsUsedSoFar++;

	/// _frame_cropping_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._frame_cropping_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_left_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_right_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_right_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_top_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_top_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
		/// _frame_crop_bottom_offset
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_seqParam[index]._frame_crop_bottom_offset);
		if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
			goto H264V2_WSPS_VLCERROR_WRITE;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
		if (bsw)
			bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WSPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_seqParam[index]._vui_parameters_present_flag);
	bitsUsedSoFar++;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: Implement VUI encoding.
	}//end if _vui_parameters_present_flag...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WriteSeqParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSeqParamSet.

/// This method has not been tested and at first glance does not look correct
int H264v2Codec::WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, bitCount;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			nextScale = scalingList[j];

			/// deltaScale
			int deltaScale = nextScale - lastScale;
			bitCount = _pHeaderSignedVlcEnc->Encode(deltaScale);  ///< se(v)
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				return(bitsUsed);
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			bitsUsed += bitCount;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end WriteSeqParamScalingList.

/** Read the sequence parameter set from the bit stream.
This impementation reads sequence parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to seq param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits, i;
	int li;
	int pi;
	int set0_flag;
	int set1_flag;
	int set2_flag;
	int set3_flag;
	int index;

	SeqParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "H264V2:[H264Codec::ReadSeqParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// The first set of bit fields are fixed with a total of 24 bits.
	if (remainingBits < 24)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// Temporarily read up to the _seq_parameter_set_id that defines the index into the
	/// _seqParam[] array.

	pi = bsr->Read(8);																		///< u(8):_profile_idc
	/// Only baseline profile is supported: _profile_idc = 66.
//	if(pi != 66)
//	{
//		_errorStr = "[H264Codec::ReadSeqParamSet] This implementation only supports the baseline profile";
//		*bitsUsed = 8;
//		return(2);
//	}//end if pi not baseline...
	set0_flag = bsr->Read();															///< u(1):_constraint_set0_flag
	set1_flag = bsr->Read();															///< u(1):_constraint_set1_flag
	set2_flag = bsr->Read();															///< u(1):_constraint_set2_flag
	set3_flag = bsr->Read();															///< u(1):_constraint_set3_flag
	bsr->Read(4);																							///< u(4), reserved_zero_4bits ignored.
	li = bsr->Read(8);																		///< u(8):_level_idc
	bitsUsedSoFar += 24;

	/// _seq_parameter_set_id
	index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the array index.
	if ((index < 0) || (index > 31))
	{
		_errorStr = "[H264Codec::ReadSeqParamSet] Sequence parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_seqParam[index]));

	/// The array index is now known and within range so the structure can be checked and loaded from the
	/// temporary variables.
	_seqParam[index]._profile_idc = pi;
	_seqParam[index]._constraint_set0_flag = set0_flag;
	_seqParam[index]._constraint_set1_flag = set1_flag;
	_seqParam[index]._constraint_set2_flag = set2_flag;
	_seqParam[index]._constraint_set3_flag = set3_flag;
	_seqParam[index]._level_idc = li;
	_seqParam[index]._seq_parameter_set_id = index;

	if ((_seqParam[index]._profile_idc == 100) || (_seqParam[index]._profile_idc == 110) ||
		(_seqParam[index]._profile_idc == 122) || (_seqParam[index]._profile_idc == 144))
	{
		/// _chroma_format_idc
		_seqParam[index]._chroma_format_idc = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		if (_seqParam[index]._chroma_format_idc == 3)
		{
			_seqParam[index]._residual_colour_transform_flag = bsr->Read(); ///< u(1)
			bitsUsedSoFar++;
		}//end if _chroma_format_idc...

		  /// _bit_depth_luma_minus8
		_seqParam[index]._bit_depth_luma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _bit_depth_chroma_minus8
		_seqParam[index]._bit_depth_chroma_minus8 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Two flags.
		_seqParam[index]._qpprime_y_zero_transform_bypass_flag = bsr->Read(); ///< u(1)
		_seqParam[index]._seq_scaling_matrix_present_flag = bsr->Read(); ///< u(1)
		bitsUsedSoFar += 2;

		/// _seq_scaling_list_present_flag[]
		if (_seqParam[index]._seq_scaling_matrix_present_flag)
		{
			for (i = 0; i < 8; i++)
			{
				_seqParam[index]._seq_scaling_list_present_flag[i] = bsr->Read(); ///< u(1)
				bitsUsedSoFar++;

				if (_seqParam[index]._seq_scaling_list_present_flag[i])
				{
					if (i < 6)
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_4x4[i], 16, &(_seqParam[index]._use_default_scaling_matrix_4x4_flag[i]));
					else
						bitsUsedSoFar += ReadSeqParamScalingList(bsr, _seqParam[index]._scaling_list_8x8[i - 6], 64, &(_seqParam[index]._use_default_scaling_matrix_8x8_flag[i - 6]));
				}//end if _seq_scaling_list_present_flag...

				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSPS_RUNOUTOFBITS_READ;
			}//end for i...
		}//end if _seq_scaling_matrix_present_flag...

	}//end if _profile_idc...

	  /// _log2_max_frame_num_minus4
	_seqParam[index]._log2_max_frame_num_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_order_cnt_type
	_seqParam[index]._pic_order_cnt_type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._pic_order_cnt_type == 0)
	{
		/// _log2_max_pic_order_cnt_lsb_minus4
		_seqParam[index]._log2_max_pic_order_cnt_lsb_minus4 = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _pic_order_cnt_type...
	else if (_seqParam[index]._pic_order_cnt_type == 1)
	{
		/// _delta_pic_order_always_zero_flag
		_seqParam[index]._delta_pic_order_always_zero_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_non_ref_pic
		_seqParam[index]._offset_for_non_ref_pic = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _offset_for_top_to_bottom_field
		_seqParam[index]._offset_for_top_to_bottom_field = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// _num_ref_frames_in_pic_order_cnt_cycle
		_seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;

		for (i = 0; i < _seqParam[index]._num_ref_frames_in_pic_order_cnt_cycle; i++)
		{
			/// _offset_for_ref_frame[256]
			_seqParam[index]._offset_for_ref_frame[i] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSPS_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSPS_RUNOUTOFBITS_READ;
		}//end for i...

	}//end else if _pic_order_cnt_type...

	/// _num_ref_frames
	_seqParam[index]._num_ref_frames = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _gaps_in_frame_num_value_allowed_flag
	_seqParam[index]._gaps_in_frame_num_value_allowed_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_width_in_mbs_minus1
	_seqParam[index]._pic_width_in_mbs_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _pic_height_in_map_units_minus1
	_seqParam[index]._pic_height_in_map_units_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_mbs_only_flag
	_seqParam[index]._frame_mbs_only_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (!_seqParam[index]._frame_mbs_only_flag)
	{
		/// _mb_adaptive_frame_field_flag
		_seqParam[index]._mb_adaptive_frame_field_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	/// _direct_8x8_inference_flag
	_seqParam[index]._direct_8x8_inference_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	/// _frame_cropping_flag
	_seqParam[index]._frame_cropping_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._frame_cropping_flag)
	{
		/// _frame_crop_left_offset
		_seqParam[index]._frame_crop_left_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_right_offset
		_seqParam[index]._frame_crop_right_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_top_offset
		_seqParam[index]._frame_crop_top_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
		/// _frame_crop_bottom_offset
		_seqParam[index]._frame_crop_bottom_offset = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSPS_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSPS_RUNOUTOFBITS_READ;
	}//end if _frame_cropping_flag...

	/// _vui_parameters_present_flag
	_seqParam[index]._vui_parameters_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSPS_RUNOUTOFBITS_READ;

	if (_seqParam[index]._vui_parameters_present_flag)
	{
		//TODO: ReadSeqParamVuiParams() does not work properly and must be debugged.
			//numBits = ReadSeqParamVuiParams(bsr);
			//bitsUsedSoFar += numBits;
			//if( bitsUsedSoFar > remainingBits )
			//	goto H264V2_RSPS_RUNOUTOFBITS_READ;

		/// Dummy read all the bits except the last one to leave the bsr pointer on the last bit.
		int pos = bsr->GetStreamBitPos();
		numBits = remainingBits - bitsUsedSoFar - 1;
		bsr->Read(numBits);
		/// Search backwards until the trailing stop bit is found.
		pos = bsr->GetStreamBitPos();
		while (bsr->Peek(pos, 1) != 1)
		{
			pos++;
			numBits--;
		}//end while Peek...
		/// Set the bsr to point at the stop bit.
		bsr->Seek(pos);
		bitsUsedSoFar += numBits;

	}//end if _vui_parameters_present_flag...

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_seqParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadSeqParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSeqParamSet.

/// This method has not been tested.
int H264v2Codec::ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix)
{
	int j, numBits;
	int bitsUsed = 0;
	int lastScale = 8;
	int nextScale = 8;

	for (j = 0; j < length; j++)
	{
		if (nextScale != 0)
		{
			/// deltaScale 
			int deltaScale = _pHeaderSignedVlcDec->Decode(bsr); ///< se(v)
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				return(bitsUsed);
			bitsUsed += numBits;

			nextScale = (lastScale + deltaScale + 256) % 256;

			if ((j == 0) && (nextScale == 0))
				*useDefaultScalingMatrix = 1;
			else
				*useDefaultScalingMatrix = 0;
		}//end if nextScale...

		if (nextScale == 0)
			scalingList[j] = lastScale;
		else
			scalingList[j] = nextScale;
		lastScale = scalingList[j];

	}//end for j...

	return(bitsUsed);
}//end ReadSeqParamScalingList.

/** Read the vui parameters from a sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	/// Aspect ratio info
	unsigned int aspect_ratio_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (aspect_ratio_info_present_flag)
	{
		unsigned int aspect_ratio_idc = bsr->Read(8); ///< u(8)
		bitsUsed += 8;
		if (aspect_ratio_idc == 255) ///< Extended_SAR
		{
			unsigned int sar_width = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
			unsigned int sar_height = bsr->Read(16); ///< u(16)
			bitsUsed += 16;
		}//end if aspect_ratio_idc...
	}//end if aspect_ratio_info_present_flag...

	/// Overscan info
	unsigned int overscan_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (overscan_info_present_flag)
	{
		unsigned int overscan_appropriate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if overscan_info_present_flag...

	/// Video signal type info
	unsigned int video_signal_type_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (video_signal_type_present_flag)
	{
		unsigned int video_format = bsr->Read(3); ///< u(3)
		bitsUsed += 3;
		unsigned int video_full_range_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int colour_description_present_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		if (colour_description_present_flag)
		{
			unsigned int colour_primaries = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int transfer_characteristics = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
			unsigned int matrix_coefficients = bsr->Read(8); ///< u(8)
			bitsUsed += 8;
		}//end if colour_description_present_flag...
	}//end if video_signal_type_present_flag...

	/// Chroma location info
	unsigned int chroma_loc_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (chroma_loc_info_present_flag)
	{
		unsigned int chroma_sample_loc_type_top_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int chroma_sample_loc_type_bottom_field = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if chroma_loc_info_present_flag...

	/// Timing info
	unsigned int timing_info_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (timing_info_present_flag)
	{
		unsigned int num_units_in_tick = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int time_scale = bsr->Read(32); ///< u(32)
		bitsUsed += 32;
		unsigned int fixed_frame_rate_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if timing_info_present_flag...

	/// HRD parameter info
	unsigned int nal_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (nal_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if nal_hrd_parameters_present_flag...
	unsigned int vcl_hrd_parameters_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (vcl_hrd_parameters_present_flag)
	{
		bitsUsed += ReadSeqParamVuiHrdParams(bsr);
	}//end if vcl_hrd_parameters_present_flag...
	if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
	{
		unsigned int low_delay_hrd_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end if nal_hrd_parameters_present_flag...

	/// Picture structure info
	unsigned int pic_struct_present_flag = bsr->Read(); ///< u(1)
	bitsUsed++;

	/// Bit stream restriction info
	unsigned int bitstream_restriction_flag = bsr->Read(); ///< u(1)
	bitsUsed++;
	if (bitstream_restriction_flag)
	{
		unsigned int motion_vectors_over_pic_boundaries_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
		unsigned int max_bytes_per_pic_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_bits_per_mb_demon = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_horizontal = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int log2_max_mv_length_vertical = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int num_reorder_frames = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int max_dec_frame_buffering = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	}//end if bitstream_restriction_flag...

	return(bitsUsed);
}//end ReadSeqParamVuiParams.

/** Read the hrd parameters from a vui sequence parameter encoded bit stream.
This is currently a dummy read without any checking.
@param bsr  : Bit stream reader to read from.
@return     : Number of bits used.
*/
int H264v2Codec::ReadSeqParamVuiHrdParams(IBitStreamReader* bsr)
{
	int bitsUsed = 0;

	unsigned int cpb_cnt_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
	bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();

	unsigned int bit_rate_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	unsigned int cpb_size_scale = bsr->Read(4); ///< u(4)
	bitsUsed += 4;

	for (unsigned int schedSelIdx = 0; schedSelIdx <= cpb_cnt_minus1; schedSelIdx++)
	{
		/// This is a dummy method but the actual method will fill bit_rate_value_minus1[schedSelIdx] array.
		unsigned int bit_rate_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cpb_size_value_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr); ///< ue(v)
		bitsUsed += _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		unsigned int cbr_flag = bsr->Read(); ///< u(1)
		bitsUsed++;
	}//end for schedSelIdx...

	unsigned int initial_cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int cpb_removal_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int dpb_output_delay_length_minus1 = bsr->Read(5); ///< u(5)
	bitsUsed += 5;
	unsigned int time_offset_length = bsr->Read(5); ///< u(5)
	bitsUsed += 5;

	return(bitsUsed);
}//endReadSeqParamVuiHrdParams. 

/** Set the Picture parameter set.
Set one of the pic param sets defined by the index parameters where the
values are determined by interpreting the codec parameters.
@param index	:	Pic parameter set to modify [0..255].
@param seqRef	: Seq param set to reference.
@return				: Success = 1, failure = 0.
*/
int H264v2Codec::SetPicParamSet(int index, int seqRef)
{
	if ((index > 255) || (seqRef > 31))
		return(0);

	_picParam[index]._pic_parameter_set_id = index;	///< The index for this definition of picture params [0..255].
	_picParam[index]._seq_parameter_set_id = seqRef;	///< This pic param set refers to this seq param set. Range = [0..31].
	_picParam[index]._entropy_coding_mode_flag = 0;			///< Baseline profile = 0. CAVLC/CABAC = 0/1.
	_picParam[index]._pic_order_present_flag = 0;			///< Pic order count syntax elements are present in the slice header.
	_picParam[index]._num_slice_groups_minus1 = 0;			///< = 0 (baseline profile). Num of slice groups for a pic.
	_picParam[index]._slice_group_map_type = 0;			///< Defines map units to slice groups. Range = [0..6].
	/// Not initialised: _run_length_minus1[7];									///< Slice group mapping.
	/// Not initialised: _top_left[7];													///< Slice group mapping.
	/// Not initialised: _bottom_right[7];											///< Slice group mapping.
	_picParam[index]._slice_group_change_direction_flag = 0;			///< Slice group mapping.
	_picParam[index]._slice_group_change_rate_minus1 = 0;			///< Slice group mapping.
	/// Not initialised: _slice_group_id[7];										///< Slice group mapping.
	_picParam[index]._num_ref_idx_l0_active_minus1 = 0;			///< Max ref index for ref pic list0.
	_picParam[index]._num_ref_idx_l1_active_minus1 = 0;			///< Max ref index for ref pic list1. (For B-Slices)
	_picParam[index]._weighted_pred_flag = 0;			///< Indicates weighted prediction applied to P-Slices.
	_picParam[index]._weighted_bipred_idc = 0;			///< Weighted prediction type applied to B-Slices.
	_picParam[index]._pic_init_qp_minus26 = 0;			///< Initial value of lum SliceQP - 26 for each slice. The slice_qp_delta modifies this value. Rng = [-26..25].
	_picParam[index]._pic_init_qs_minus26 = 0;			///< For SP and SI slices.
	_picParam[index]._chroma_qp_index_offset = 0;			///< Offset added to lum QP (and QS) for Cb chr QP values. Rng = [-12..12].
	_picParam[index]._second_chroma_qp_index_offset = 0;			///< For Cr chr QP. When not present = _chroma_qp_index_offset above.
	_picParam[index]._deblocking_filter_control_present_flag = 0;			///< Indicates presence of elements in slice header to change the characteristics of the deblocking filter.
	_picParam[index]._constrained_intra_pred_flag = 1;			///< = 1. Indicates that intra macroblock prediction can only be done from other intra macroblocks. 
	_picParam[index]._redundant_pic_cnt_present_flag = 0;			///< Indicates that redundant pic count elements are in the slice header.
	_picParam[index]._transform_8x8_mode_flag = 0;			///< = 0. Indicates 8x8 transform is used. When not present = 0.
	_picParam[index]._pic_scaling_matrix_present_flag = 0;			///< = 0. Indicates params are present to modify the scaling lists specified in the seq param sets.
	/// Not initialised:_pic_scaling_list_present_flag[8];			///< Scaling list syntax structure present for scaling list i = 0..7.

	_picParam[index]._pic_size_in_map_units_minus1 = ((_width / 16)*(_height / 16)) - 1;	///< Num of map units (macroblocks for frames) in the pic. Macroblock width * height.

	return(1);
}//end SetPicParamSet.

/** Write the picture parameter set to a bit stream.
The pic param set must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit
overflow will occur before writing. The check is sufficiently frequent to
warrant an early exit GOTO statement. If the input stream param is NULL then
this method is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@param index				: Picture parameter set index to write.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2, unsupported parameter set = 3.
*/
int H264v2Codec::WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index)
{
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// _pic_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._pic_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _seq_parameter_set_id
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._seq_parameter_set_id);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _entropy_coding_mode_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._entropy_coding_mode_flag);
	bitsUsedSoFar++;

	/// _pic_order_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._pic_order_present_flag);
	bitsUsedSoFar++;

	/// _num_slice_groups_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_slice_groups_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_WPPS_MODEERROR_WRITE;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l0_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _num_ref_idx_l1_active_minus1
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_picParam[index]._num_ref_idx_l1_active_minus1);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _weighted_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._weighted_pred_flag);
	bitsUsedSoFar++;

	/// _weighted_bipred_idc
	if ((bitsUsedSoFar + 2) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(2, _picParam[index]._weighted_bipred_idc);
	bitsUsedSoFar += 2;

	/// _pic_init_qp_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qp_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _pic_init_qs_minus26
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._pic_init_qs_minus26);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _chroma_qp_index_offset
	bitCount = _pHeaderSignedVlcEnc->Encode(_picParam[index]._chroma_qp_index_offset);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_WPPS_VLCERROR_WRITE;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// _deblocking_filter_control_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._deblocking_filter_control_present_flag);
	bitsUsedSoFar++;

	/// _constrained_intra_pred_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._constrained_intra_pred_flag);
	bitsUsedSoFar++;

	/// _redundant_pic_cnt_present_flag
	if ((bitsUsedSoFar + 1) > allowedBits)
		goto H264V2_WPPS_RUNOUTOFBITS_WRITE;
	if (bsw)
		bsw->Write(_picParam[index]._redundant_pic_cnt_present_flag);
	bitsUsedSoFar++;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WPPS_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WPPS_VLCERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WPPS_MODEERROR_WRITE:
	_errorStr = "H264V2:[H264Codec::WritePicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WritePicParamSet.

/** Read the picture parameter set from the bit stream.
This impementation reads picture parameter set encodings. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync wherever possible.
The checks are sufficiently frequent to warrant an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@param idx						: Reference to pic param set index read.
@param changedFlag    : Flag to indicate that param set has changed to a new one.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag)
{
	int bitsUsedSoFar = 0;
	int numBits;
	PicParamSetH264 tmpParamSet;

	/// Check existance of stream reader.
	if (bsr == NULL)
	{
		_errorStr = "[H264Codec::ReadPicParamSet] No bit stream reader available";
		*bitsUsed = 0;
		return(2);
	}//end if bsr...

	/// _pic_parameter_set_id
	int index = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;
	*idx = index;

	/// Range check on the pic param array index.
	if ((index < 0) || (index > 255))
	{
		_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter set index out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

  /// Store the current set.
	tmpParamSet.Copy(&(_picParam[index]));

	/// The decoded index identifies the param set to use.
	_picParam[index]._pic_parameter_set_id = index;

	/// _seq_parameter_set_id
	_picParam[index]._seq_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// Range check on the seq param array index. This does not test if the data in the _seqParam[]
	/// array for this id is valid.
	if ((_picParam[index]._seq_parameter_set_id < 0) || (_picParam[index]._seq_parameter_set_id > 31))
	{
		_errorStr = "H264V2:[H264Codec::ReadPicParamSet] Sequence parameter set index of picture parameter set is out of range";
		*bitsUsed = bitsUsedSoFar;
		return(2);
	}//end if index...

	/// _entropy_coding_mode_flag
	_picParam[index]._entropy_coding_mode_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_order_present_flag
	_picParam[index]._pic_order_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_slice_groups_minus1
	_picParam[index]._num_slice_groups_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	if (_picParam[index]._num_slice_groups_minus1 > 0)
	{
		// TODO: Add support for slice groups here
		goto H264V2_RPPS_NOMODE_READ;

		/// _slice_group_map_type, _run_length_minus1[7], _top_left[7], _bottom_right[7], _slice_group_change_direction_flag,
		/// _slice_group_change_rate_minus1, _pic_size_in_map_units_minus1, _slice_group_id[].
	}//end if _num_slice_groups_minus1...

	/// _num_ref_idx_l0_active_minus1
	_picParam[index]._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _num_ref_idx_l1_active_minus1
	_picParam[index]._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_pred_flag
	_picParam[index]._weighted_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _weighted_bipred_idc
	_picParam[index]._weighted_bipred_idc = bsr->Read(2);
	bitsUsedSoFar += 2;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qp_minus26
	_picParam[index]._pic_init_qp_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _pic_init_qs_minus26
	_picParam[index]._pic_init_qs_minus26 = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _chroma_qp_index_offset
	_picParam[index]._chroma_qp_index_offset = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RPPS_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _deblocking_filter_control_present_flag
	_picParam[index]._deblocking_filter_control_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _constrained_intra_pred_flag
	_picParam[index]._constrained_intra_pred_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	/// _redundant_pic_cnt_present_flag
	_picParam[index]._redundant_pic_cnt_present_flag = bsr->Read();
	bitsUsedSoFar++;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RPPS_RUNOUTOFBITS_READ;

	//TODO: Implement if more_rbsp_data() section here.
	/// _transform_8x8_mode_flag, _pic_scaling_matrix_present_flag, _pic_scaling_list_present_flag[8],
	/// _second_chroma_qp_index_offset.

  /// Check if this new set is different to the old stored at this index.
	*changedFlag = 1;
	if (tmpParamSet.Equals(&(_picParam[index])))
		*changedFlag = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RPPS_RUNOUTOFBITS_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RPPS_NOVLC_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RPPS_NOMODE_READ:
	_errorStr = "[H264Codec::ReadPicParamSet] Picture parameter not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadPicParamSet.

/** Get the codec parameters.
Load the codec params from the picture param set indexed by
the input param. The sequence param set is implied in the referenced
pic param set. The pic/seq param set must be previously defined
prior to calling this method.
@param picParamSet	:	Pic parameter set to get from [0..255].
@return							: Success = 1, failure = 0.
*/
int H264v2Codec::GetCodecParams(int picParamSet)
{
	///----------- Some parameter set range checking ------------------------------
	if ((picParamSet < 0) || (picParamSet > 255))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set out of range";
		return(0);
	}//end if picParamSet...
	if (_picParam[picParamSet]._pic_parameter_set_id != picParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameter set mismatch";
		return(0);
	}//end if _pic_parameter_set_id...
	int seqParamSet = _picParam[picParamSet]._seq_parameter_set_id;
	if ((seqParamSet < 0) || (seqParamSet > 31))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set out of range";
		return(0);
	}//end if seqParamSet...
	if (_seqParam[seqParamSet]._seq_parameter_set_id != seqParamSet)
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameter set mismatch";
		return(0);
	}//end if _seq_parameter_set_id...
	/// Modify the codec seq param set to that associated with this pic param set.
	_currSeqParam = seqParamSet;

	///----------- Extract params of interest for codec -----------------------
	/// Get width and height in pels.
	_width = (_seqParam[seqParamSet]._pic_width_in_mbs_minus1 + 1) * 16;
	_height = (_seqParam[seqParamSet]._pic_height_in_map_units_minus1 + 1) * 16;
	_seqParamSetLog2MaxFrameNumMinus4 = _seqParam[seqParamSet]._log2_max_frame_num_minus4;

	///----------- Check params for this implementation -----------------------

	/// Sequence parameter implementation.
	if ((_seqParam[seqParamSet]._profile_idc != 66) ||
		(_seqParam[seqParamSet]._constraint_set0_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set1_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set2_flag != 0) ||
		(_seqParam[seqParamSet]._constraint_set3_flag != 0) ||
		(_seqParam[seqParamSet]._level_idc != 20) ||
		(_seqParam[seqParamSet]._chroma_format_idc != 1) ||
		(_seqParam[seqParamSet]._bit_depth_luma_minus8 != 0) ||
		(_seqParam[seqParamSet]._bit_depth_chroma_minus8 != 0) ||
		(_seqParam[seqParamSet]._qpprime_y_zero_transform_bypass_flag != 0) ||
		(_seqParam[seqParamSet]._seq_scaling_matrix_present_flag != 0) ||
		(_seqParam[seqParamSet]._pic_order_cnt_type != 2) ||
		(_seqParam[seqParamSet]._num_ref_frames != 1) ||
		(_seqParam[seqParamSet]._gaps_in_frame_num_value_allowed_flag != 0) ||
		(_seqParam[seqParamSet]._frame_mbs_only_flag != 1) ||
		(_seqParam[seqParamSet]._mb_adaptive_frame_field_flag != 0) ||
		(_seqParam[seqParamSet]._direct_8x8_inference_flag != 0) ||
		(_seqParam[seqParamSet]._frame_cropping_flag != 0) ||
		(_seqParam[seqParamSet]._vui_parameters_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Sequence parameters not implemented";
		return(0);
	}//end if _profile_idc...

	/// Picture parameter implementation.
	if ((_picParam[picParamSet]._entropy_coding_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_order_present_flag != 0) ||
		(_picParam[picParamSet]._num_slice_groups_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l0_active_minus1 != 0) ||
		(_picParam[picParamSet]._num_ref_idx_l1_active_minus1 != 0) ||
		(_picParam[picParamSet]._weighted_pred_flag != 0) ||
		(_picParam[picParamSet]._weighted_bipred_idc != 0) ||
		(_picParam[picParamSet]._constrained_intra_pred_flag != 1) ||
		(_picParam[picParamSet]._redundant_pic_cnt_present_flag != 0) ||
		(_picParam[picParamSet]._transform_8x8_mode_flag != 0) ||
		(_picParam[picParamSet]._pic_scaling_matrix_present_flag != 0))
	{
		_errorStr = "[H264Codec::GetCodecParams] Picture parameters not implemented";
		return(0);
	}//end if _profile_idc...

	return(1);
}//end GetCodecParams.

/** Write the NAL header to a bit stream.
The NAL header data must be correctly defined before this method is called. The
vlc encoding is performed first before writing. Each write checks if a bit overflow
will occur before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (allowedBits >= 8)
	{
		if (bsw)
		{
			bsw->Write(1, 0);												///< Forbidden zero bit f(1).
			bsw->Write(2, (_nal._ref_idc & 3));			///< u(2).		
			bsw->Write(5, (_nal._unit_type & 31));	///< u(5).		
		}//end if bsw != NULL...
	}//end if allowedBits...
	else
	{
		_errorStr = "H264V2:[WriteNALHeader] Bits required exceeds max available for NAL header";
		*bitsUsed = 0;
		return(1);
	}///end else...

	*bitsUsed = 8;
	return(0);
}//end WriteNALHeader.

/** Read the NAL header from the bit stream.
This impementation reads the NAL header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	/// The NAL header is a fixed 8 bit sequence.
	if (remainingBits >= 8)
	{
		bsr->Read();													///< Discard forbidden zero bit f(1).
		_nal._ref_idc = 3 & bsr->Read(2);		///< u(2).
		_nal._unit_type = 31 & bsr->Read(5);	///< u(5).
	}//end if remainingBits...
	else
	{
		_errorStr = "H264V2:[ReadNALHeader] Insufficient bits to decode the NAl header";
		*bitsUsed = 0;
		return(1);
	}//end else...

	*bitsUsed = 8;
	return(0);
}//end ReadNALHeader.

/** Write the slice layer header to a bit stream.
The encodings of all the slice data must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. Each write checks if a bit overflow will occur before writing.
The check is sufficiently frequent to warrant an early exit GOTO
statement. If the input stream param is NULL then this method is used
to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int	  bitCount;
	int   bitsUsedSoFar = 0;
	char  errInfo[64];
	char  buff[64];

		/// Limited implementation of modes and types for Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_WSLH_MODEERROR_WRITE;

	///-------------------------- Addr of first macroblock -----------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._first_mb_in_slice);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_first_mb_in_slice=");
		sprintf((char *)buff, "%d", _slice._first_mb_in_slice);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._first_mb_in_slice, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Slice Type -------------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._type);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_type=");
		sprintf((char *)buff, "%d", _slice._type);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._type, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Pic Param Set Id --------------------------------------------
	bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._pic_parameter_set_id);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_pic_parameter_set_id=");
		sprintf((char *)buff, "%d", _slice._pic_parameter_set_id);
		strcat(errInfo, buff);
		// strcat(errInfo, itoa(_slice._pic_parameter_set_id, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Frame Number -----------------------------------------------
	bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	if ((bitsUsedSoFar + bitCount) <= allowedBits)
	{
		if (bsw)
			bsw->Write(bitCount, _slice._frame_num);
	}//end if bitsUsedSoFar...
	else
		goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	bitsUsedSoFar += bitCount;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		if ((bitsUsedSoFar + 2) <= allowedBits)	///< Both flags together.
		{
			if (bsw)
				bsw->Write(_slice._field_pic_flag);
			bitsUsedSoFar++;
			if (_slice._field_pic_flag)
			{
				if (bsw)
					bsw->Write(_slice._bottom_field_flag);
				bitsUsedSoFar++;
			}//end if _field_pic_flag...
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._idr_pic_id);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
				{
					if (bitCount <= 32)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					else
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetExtCode(), _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bsw...
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_idr_pic_id=");
			sprintf((char *)buff, "%d", _slice._idr_pic_id);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._idr_pic_id, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		bitCount = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _slice._pic_order_cnt_lsb);
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt_bottom);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt_bottom=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt_bottom);
				strcat(errInfo, buff);
				// strcat(errInfo, itoa(_slice._delta_pic_order_cnt_bottom, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[0]);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_delta_pic_order_cnt[0]=");
			sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[0]);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[0], buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._delta_pic_order_cnt[1]);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_delta_pic_order_cnt[1]=");
				sprintf((char *)buff, "%d", _slice._delta_pic_order_cnt[1]);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._delta_pic_order_cnt[1], buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._redundant_pic_cnt);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_redundant_pic_cnt=");
			sprintf((char *)buff, "%d", _slice._redundant_pic_cnt);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._redundant_pic_cnt, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._direct_spatial_mv_pred_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::B_Slice) ||
		(_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._num_ref_idx_active_override_flag);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._num_ref_idx_active_override_flag)
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l0_active_minus1);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_num_ref_idx_l0_active_minus1=");
				sprintf((char *)buff, "%d", _slice._num_ref_idx_l0_active_minus1);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._num_ref_idx_l0_active_minus1, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice))
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._num_ref_idx_l1_active_minus1);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_num_ref_idx_l1_active_minus1=");
					sprintf((char *)buff, "%d", _slice._num_ref_idx_l1_active_minus1);
					strcat(errInfo, buff);
					//strcat(errInfo, itoa(_slice._num_ref_idx_l1_active_minus1, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		if ((bitsUsedSoFar + 1) <= allowedBits)
		{
			if (bsw)
				bsw->Write(_slice._ref_pic_list_reordering_flag_l0);
			bitsUsedSoFar++;
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._reordering_of_pic_nums_idc);
				if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
				{
					if ((bitsUsedSoFar + bitCount) <= allowedBits)
					{
						if (bsw)
							bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
					}//end if bitsUsedSoFar...
					else
						goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
				}//end if bitCount...
				else
				{
					strcpy(errInfo, "_reordering_of_pic_nums_idc=");
					sprintf((char *)buff, "%d", _slice._reordering_of_pic_nums_idc);
					strcat(errInfo, buff);
					// strcat(errInfo, itoa(_slice._reordering_of_pic_nums_idc, buff, 10));
					goto H264V2_WSLH_VLCERROR_WRITE;
				}//end else...
				bitsUsedSoFar += bitCount;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{

					// TODO: Prepare list 0 reordering with _slice._abs_diff_pic_num_minus1.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._abs_diff_pic_num_minus1);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_abs_diff_pic_num_minus1=");
						sprintf((char *)buff, "%d", _slice._abs_diff_pic_num_minus1);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._abs_diff_pic_num_minus1, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{

					// TODO: Prepare list 0 reordering with _slice._long_term_pic_num.

					bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._long_term_pic_num);
					if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
					{
						if ((bitsUsedSoFar + bitCount) <= allowedBits)
						{
							if (bsw)
								bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
						}//end if bitsUsedSoFar...
						else
							goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
					}//end if bitCount...
					else
					{
						strcpy(errInfo, "_long_term_pic_num=");
						sprintf((char *)buff, "%d", _slice._long_term_pic_num);
						strcat(errInfo, buff);
						//strcat(errInfo, itoa(_slice._long_term_pic_num, buff, 10));
						goto H264V2_WSLH_VLCERROR_WRITE;
					}//end else...
					bitsUsedSoFar += bitCount;
				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...

	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_WSLH_MODEERROR_WRITE;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			if ((bitsUsedSoFar + 2) <= allowedBits)
			{
				if (bsw)
				{
					bsw->Write(_slice._no_output_of_prior_pics_flag);
					bsw->Write(_slice._long_term_reference_flag);
				}//end if bsw...
				bitsUsedSoFar += 2;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if IDR_Slice...
		else
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._adaptive_ref_pic_marking_mode_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_WSLH_MODEERROR_WRITE;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation ----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._cabac_init_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_cabac_init_idc=");
			sprintf((char *)buff, "%d", _slice._cabac_init_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._cabac_init_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qp_delta);
	if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
	{
		if ((bitsUsedSoFar + bitCount) <= allowedBits)
		{
			if (bsw)
				bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
		}//end if bitsUsedSoFar...
		else
			goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
	}//end if bitCount...
	else
	{
		strcpy(errInfo, "_qp_delta=");
		sprintf((char *)buff, "%d", _slice._qp_delta);
		strcat(errInfo, buff);
		//strcat(errInfo, itoa(_slice._qp_delta, buff, 10));
		goto H264V2_WSLH_VLCERROR_WRITE;
	}//end else...
	bitsUsedSoFar += bitCount;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SI_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice_All) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			if ((bitsUsedSoFar + 1) <= allowedBits)
			{
				if (bsw)
					bsw->Write(_slice._sp_for_switch_flag);
				bitsUsedSoFar++;
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if SP_Slice...

		bitCount = _pHeaderSignedVlcEnc->Encode(_slice._qs_delta);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_qs_delta=");
			sprintf((char *)buff, "%d", _slice._qs_delta);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._qs_delta, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		bitCount = _pHeaderUnsignedVlcEnc->Encode(_slice._disable_deblocking_filter_idc);
		if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
		{
			if ((bitsUsedSoFar + bitCount) <= allowedBits)
			{
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			}//end if bitsUsedSoFar...
			else
				goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
		}//end if bitCount...
		else
		{
			strcpy(errInfo, "_disable_deblocking_filter_idc=");
			sprintf((char *)buff, "%d", _slice._disable_deblocking_filter_idc);
			strcat(errInfo, buff);
			//strcat(errInfo, itoa(_slice._disable_deblocking_filter_idc, buff, 10));
			goto H264V2_WSLH_VLCERROR_WRITE;
		}//end else...
		bitsUsedSoFar += bitCount;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._alpha_c0_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_alpha_c0_offset_div2=");
				sprintf((char *)buff, "%d", _slice._alpha_c0_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._alpha_c0_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;

			bitCount = _pHeaderSignedVlcEnc->Encode(_slice._beta_offset_div2);
			if (bitCount > 0)	///< Vlc codec errors are detected from a zero or negative return value.
			{
				if ((bitsUsedSoFar + bitCount) <= allowedBits)
				{
					if (bsw)
						bsw->Write(bitCount, _pHeaderSignedVlcEnc->GetCode());
				}//end if bitsUsedSoFar...
				else
					goto H264V2_WSLH_RUNOUTOFBITS_WRITE;
			}//end if bitCount...
			else
			{
				strcpy(errInfo, "_beta_offset_div2=");
				sprintf((char *)buff, "%d", _slice._beta_offset_div2);
				strcat(errInfo, buff);
				//strcat(errInfo, itoa(_slice._beta_offset_div2, buff, 10));
				goto H264V2_WSLH_VLCERROR_WRITE;
			}//end else...
			bitsUsedSoFar += bitCount;
		}//end if _disable_deblocking_filter_idc...

	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_WSLH_MODEERROR_WRITE;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_WSLH_RUNOUTOFBITS_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_WSLH_VLCERROR_WRITE:
	strcpy(_errorInfo, "[H264v2Codec::WriteSliceLayerHeader] Vlc encoder error: ");
	strcat(_errorInfo, errInfo);
	_errorStr = _errorInfo;
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_WSLH_MODEERROR_WRITE:
	_errorStr = "[H264v2Codec::WriteSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceLayerHeader.

/** Read the slice layer header from the bit stream.
This impementation reads slice header encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of vlc sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int numBits;

	if (bsr == NULL)
	{
		_errorStr = "[H264V2::ReadSliceLayerHeader] No bit stream reader";
		*bitsUsed = 0;
		return(2);
	}//end if !bsr...

	///-------------------------- Addr of first macroblock -----------------------------------
	_slice._first_mb_in_slice = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Slice Type -------------------------------------------------
	_slice._type = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	/// Limited implementation of slice types and modes for the Baseline profile.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::I_Slice_All) &&
		(_slice._type != SliceHeaderH264::P_Slice) && (_slice._type != SliceHeaderH264::P_Slice_All))
		goto H264V2_RSLH_NOMODE_READ;

	///-------------------------- Pic Param Set Id --------------------------------------------
	_slice._pic_parameter_set_id = _pHeaderUnsignedVlcDec->Decode(bsr);
	numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Frame Number ----------------------------------------------
	numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_frame_num_minus4 + 4;
	_slice._frame_num = bsr->Read(numBits);
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Field Flags ----------------------------------------------
	if (!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._frame_mbs_only_flag)
	{
		_slice._field_pic_flag = bsr->Read();
		bitsUsedSoFar++;
		if (_slice._field_pic_flag)
		{
			_slice._bottom_field_flag = bsr->Read();
			bitsUsedSoFar++;
		}//end if _field_pic_flag...
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if !_frame_mbs_only_flag...

	///-------------------------- IDR Frame Count ------------------------------------------
	if (_nal._unit_type == NalHeaderH264::IDR_Slice)
	{
		_slice._idr_pic_id = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _unit_type...

	///-------------------------- Picture Order Count ---------------------------------------
	if (_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 0)
	{
		numBits = _seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._log2_max_pic_order_cnt_lsb_minus4 + 4;
		_slice._pic_order_cnt_lsb = bsr->Read(numBits);
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt_bottom = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...

	}//end if _pic_order_cnt_type...
	else if ((_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._pic_order_cnt_type == 1) &&
		!_seqParam[_picParam[_slice._pic_parameter_set_id]._seq_parameter_set_id]._delta_pic_order_always_zero_flag)
	{
		_slice._delta_pic_order_cnt[0] = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_picParam[_slice._pic_parameter_set_id]._pic_order_present_flag && !_slice._field_pic_flag)
		{
			_slice._delta_pic_order_cnt[1] = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _pic_order_present_flag...
	}//end else if _pic_order_cnt_type...

	if (_picParam[_slice._pic_parameter_set_id]._redundant_pic_cnt_present_flag)
	{
		_slice._redundant_pic_cnt = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _redundant_pic_cnt_present_flag...

	///-------------------------- Direct Spatial Prediction -----------------------------------
	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._direct_spatial_mv_pred_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if B_Slice...

	///-------------------------- Active Reference Indices -----------------------------------
	if ((_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::P_Slice) ||
		(_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		_slice._num_ref_idx_active_override_flag = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._num_ref_idx_active_override_flag)
		{
			_slice._num_ref_idx_l0_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
			{
				_slice._num_ref_idx_l1_active_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;
			}//end if B_Slice...
		}//end if _num_ref_idx_active_override_flag...
	}//end if P_Slice...

	///-------------------------- Reference Pic list reordering --------------------------------
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._ref_pic_list_reordering_flag_l0 = bsr->Read();
		bitsUsedSoFar++;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._ref_pic_list_reordering_flag_l0)
		{
			do
			{
				_slice._reordering_of_pic_nums_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
				numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
				if (numBits == 0)	///< Return = 0 implies no valid vlc code.
					goto H264V2_RSLH_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RSLH_RUNOUTOFBITS_READ;

				if ((_slice._reordering_of_pic_nums_idc == 0) || (_slice._reordering_of_pic_nums_idc == 1))
				{
					_slice._abs_diff_pic_num_minus1 = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._abs_diff_pic_num_minus1.
					goto H264V2_RSLH_NOMODE_READ;

				}//end if _reordering_of_pic_nums_idc...
				else if (_slice._reordering_of_pic_nums_idc == 2)
				{
					_slice._long_term_pic_num = _pHeaderUnsignedVlcDec->Decode(bsr);
					numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
					if (numBits == 0)	///< Return = 0 implies no valid vlc code.
						goto H264V2_RSLH_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RSLH_RUNOUTOFBITS_READ;

					// TODO: Handle list 0 reordering with _slice._long_term_pic_num.
					goto H264V2_RSLH_NOMODE_READ;

				}//end else if _reordering_of_pic_nums_idc...

			} while (_slice._reordering_of_pic_nums_idc != 3);
		}//end if _ref_pic_list_reordering_flag_l0...
	}//end if !I_Slice...

	if ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))
	{
		/// B Slices are not supported for the baseline profile.
		// TODO: B-slice reordering syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if B_Slice...

	///-------------------------- Weighted Prediction Table --------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._weighted_pred_flag && ((_slice._type == SliceHeaderH264::P_Slice) || (_slice._type == SliceHeaderH264::P_Slice_All) || (_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))) ||
		((_picParam[_slice._pic_parameter_set_id]._weighted_bipred_idc == 1) && ((_slice._type == SliceHeaderH264::B_Slice) || (_slice._type == SliceHeaderH264::B_Slice_All))))
	{
		// TODO: Prediction Weight Table syntax.
		goto H264V2_RSLH_NOMODE_READ;
	}//end if ...

	///-------------------------- Decode Reference Pic Marking  --------------------------------
	if (_nal._ref_idc != 0)
	{
		if (_nal._unit_type == NalHeaderH264::IDR_Slice)
		{
			_slice._no_output_of_prior_pics_flag = bsr->Read();
			_slice._long_term_reference_flag = bsr->Read();
			bitsUsedSoFar += 2;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if IDR_Slice...
		else
		{
			_slice._adaptive_ref_pic_marking_mode_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			if (_slice._adaptive_ref_pic_marking_mode_flag)
			{
				// TODO: Implement Adaptive reference pic marking mode.
				goto H264V2_RSLH_NOMODE_READ;
			}//end if _adaptive_ref_pic_marking_mode_flag...

		}//end else...
	}//end if _ref_idc...

	///-------------------------- CABAC initialisation  ---------------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._entropy_coding_mode_flag &&
		(_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_slice._cabac_init_idc = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if _entropy_coding_mode_flag...

	///-------------------------- Delta Quant Param ---------------------------------------
	_slice._qp_delta = _pHeaderSignedVlcDec->Decode(bsr);
	numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
	if (numBits == 0)	///< Return = 0 implies no valid vlc code.
		goto H264V2_RSLH_NOVLC_READ;
	bitsUsedSoFar += numBits;
	if (bitsUsedSoFar > remainingBits)
		goto H264V2_RSLH_RUNOUTOFBITS_READ;

	///-------------------------- Switching slices ---------------------------------------
	if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All) ||
		(_slice._type == SliceHeaderH264::SI_Slice) || (_slice._type == SliceHeaderH264::SI_Slice_All))
	{
		if ((_slice._type == SliceHeaderH264::SP_Slice) || (_slice._type == SliceHeaderH264::SP_Slice_All))
		{
			_slice._sp_for_switch_flag = bsr->Read();
			bitsUsedSoFar++;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if SP_Slice...

		_slice._qs_delta = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;
	}//end if SP_Slice...

	///-------------------------- Deblocking Filter Control -----------------------------------
	if (_picParam[_slice._pic_parameter_set_id]._deblocking_filter_control_present_flag)
	{
		_slice._disable_deblocking_filter_idc = _pHeaderSignedVlcDec->Decode(bsr);
		numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_RSLH_NOVLC_READ;
		bitsUsedSoFar += numBits;
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RSLH_RUNOUTOFBITS_READ;

		if (_slice._disable_deblocking_filter_idc != 1)
		{
			_slice._alpha_c0_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;

			_slice._beta_offset_div2 = _pHeaderSignedVlcDec->Decode(bsr);
			numBits = _pHeaderSignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_RSLH_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RSLH_RUNOUTOFBITS_READ;
		}//end if _disable_deblocking_filter_idc...
	}//end if _deblocking_filter_control_present_flag...

	///-------------------------- Slice Groups ---------------------------------------------
	if ((_picParam[_slice._pic_parameter_set_id]._num_slice_groups_minus1 > 0) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type >= 3) &&
		(_picParam[_slice._pic_parameter_set_id]._slice_group_map_type <= 5))
	{
		// TODO: Implement slice group handling.
		goto H264V2_RSLH_NOMODE_READ;

	}//end if _num_slice_groups_minus1...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RSLH_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_RSLH_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_RSLH_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceLayerHeader] Slice type or mode not implemented";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end ReadSliceLayerHeader.

/** Write trailing bits to a bit stream.
A stop 1 bit is written and then zero bits are written until a byte boundary. Each
write checks if a bit overflow will occur before writing the stop bit. The zeros
are not counted in the bitsUsed. If the input stream param is NULL then this method
is used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0.
*/
int H264v2Codec::WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	/// Write the stop bit.
	if (allowedBits < 1)
	{
		_errorStr = "H264V2:[WriteTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if allowedBits...
	if (bsw)
		bsw->Write(1);
	bitsUsedSoFar++;

	/// Write zeros to the end of the byte. Do not count the trailing zeros.
	if (bsw)
	{
		int toByteBoundary = (bsw->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Do not allow the last byte to be 0x00
			bsw->Write(toByteBoundary, 0);
		//bitsUsedSoFar += toByteBoundary;
	}//end if bsw...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}// end WriteTrailingBits.

/** Read trailing bits from the bit stream.
This impementation reads the trailing bit encoding. Each read checks if a
bit underflow will occur after reading. Check for loss of sync
wherever possible. The checks are sufficiently frequent to warrant
an early exit GOTO statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 3.
*/
int H264v2Codec::ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;
	int bit = 1;

	if (remainingBits < 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] Run out of bits";
		*bitsUsed = 0;
		return(1);
	}//end if remainingBits...

	/// Read stop bit.
	if (bsr)
		bit = bsr->Read();
	bitsUsedSoFar++;
	if (bit != 1)
	{
		_errorStr = "H264V2:[ReadTrailingBits] No stop bit detected";
		*bitsUsed = bitsUsedSoFar;
		return(3);
	}//end if !stop bit...

	/// Read zeros up to the end of the byte. Do not count the trailing zeros.
	if (bsr)
	{
		int toByteBoundary = (bsr->GetStreamBitPos() % 8) + 1;
		if (toByteBoundary < 8)  ///< Only read zeros within the same byte as the stop bit.
		{
			bit = bsr->Read(toByteBoundary);
			//bitsUsedSoFar += toByteBoundary;
			if (bit != 0)
			{
				_errorStr = "H264V2:[ReadTrailingBits] Missing trailing zeros";
				*bitsUsed = bitsUsedSoFar;
				return(3);
			}//end if !zero bits...
		}//end if toByteBoundary...
	}//end if bsr...

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadTrailingBits.

/** Insert start code emulation prevention codes.
Scan the entire stream, excluding the 32 bit actual start code, and check
for 24 bit 0x000000 - 0x000003 sequences. Replace them with 32 bit
0x00000300 - 0x00000303 sequences. The extra byte (8 bits) for each
emulation code is excluded from the number of allowed bits but is added
to the total consumed bits. [NB: Care must be taken when checking for
running out of bits to allow for these extra codes.] This method should
only be called once the entire frame has been encoded.
@param bsw	        : Stream to write into.
@param startOffset  : Start evaluating the stream from a byte offset.
@return			        : Return the number of extra bits inserted.
*/
int H264v2Codec::InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset)
{
	if (bsw == NULL)
		return(0);

	int count = 0;

	unsigned char*  streamHead = (unsigned char*)(bsw->GetStream());
	unsigned char*  stream = &(streamHead[startOffset]);

	/// It is assumed that the stream is fully encoded and the trailing bits have been added
	/// to ensure byte alignement of the stream. Therefore the current stream byte pos is the 
	/// number of encoded bytes in the stream.
	int  endPos = bsw->GetStreamBytePos() - 1 - startOffset;
	if (endPos < 2) return(0);

	/// Find the occurrance of the start code emulation then shift down by copying backwards from the end. Note
	/// that 1st 4 bytes are the start code 0x00000001.
	for (int pos = 6; pos <= endPos; pos++)
	{
		if ((stream[pos] & 0xFC) == 0) ///< Check for 0, 1, 2 or 3.
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0)) ///< Check 2 preceeding bytes are zero.
			{
				for (int i = endPos; i >= pos; i--) ///< Shift down by 1 byte.
					stream[i + 1] = stream[i];
				stream[pos] = 0x03; ///< Insert emulation prevention code.
				pos++;              ///< Continue from new shifted position.
				endPos++;           ///< Last byte is now shifted by 1 position.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end InsertEmulationPrevention.

/** Remove start code emulation prevention codes.
Scan the entire stream and check for 24 bit 0x000003 sequence
and remove the 0x03 byte from the stream. This method should
only be called once before decoding the entire frame.
@param bsr	: Stream to read from.
@return			: Return the number of extra bits removed.
*/
int H264v2Codec::RemoveEmulationPrevention(IBitStreamReader* bsr)
{
	if (bsr == NULL)
		return(0);

	int count = 0;

	unsigned char*  stream = (unsigned char*)(bsr->GetStream());
	int             bits = bsr->GetStreamBitSize();
	int             endPos = (bits / 8) - 1;
	if ((bits % 8) != 0)
		endPos++;

	/// Find the 1st occurrence of the emulation prevention code.
	int pos;
	for (pos = 2; pos <= endPos; pos++)
	{
		if (stream[pos] == 0x03) ///< Emulation prevention code = 0x03...
		{
			if ((stream[pos - 1] == 0) && (stream[pos - 2] == 0))  ///< ...and is preceeded by 2 zero bytes.
			{
				/// Shift remaining bytes up by 1 byte.
				for (int i = pos; i < endPos; i++)
					stream[i] = stream[i + 1];
				pos++;    ///< Skip one to prevent trapping a 0x00 followed by a 0x03 in the actual stream.
				endPos--; ///< Last byte was shifted by 1.
				count++;
			}//end if stream...
		}//end if stream...
	}//end for pos...

	return(count * 8);
}// end RemoveEmulationPrevention.

/** Write the slice data layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes every macroblock encoding in top-left
to bottom-right order. Each write checks if a bit overflow will occur
before writing. The check is sufficiently frequent to warrant an early
exit GOTO statement. If the input stream param is NULL then this method is
used to count the bits only.
@param bsw					: Stream to write into.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed)
{
	int mb, i;
	int	bitCount;
	int bitsUsedSoFar = 0;

	/// All macroblocks are written in order.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// ------------------------ Code the slice data -----------------------------------
	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		if (!pMb->_skip)	///< Encoding must set the _skip flag even for Intra macroblocks.
		{
			if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
				(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
			{
				/// ------------------------ Code the skip run -----------------------------------
				bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
				if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
					goto H264V2_VLCERROR_WRITE;
				if ((bitsUsedSoFar + bitCount) > allowedBits)
					goto H264V2_RUNOUTOFBITS_WRITE;
				if (bsw)
					bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
				bitsUsedSoFar += bitCount;

				_mb_skip_run = 0;	///< ...and reset.
			}//end if !I_Slice...

			/// ------------------------ Code the macroblock data ------------------------------------
			/// Only non-skipped macroblocks call this method.
			int ret = WriteMacroBlockLayer(bsw, pMb, allowedBits - bitsUsedSoFar, &bitCount);
			if (ret) ///< An error has occurred.
			{
				/// _errorStr was set in the WriteMacroBlockLayer() method.
				*bitsUsed = bitsUsedSoFar + bitCount;
				return(ret);
			}//end if ret...
			bitsUsedSoFar += bitCount;
		}//end if !_skip...
		else
		{
			_mb_skip_run++;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end else...

	}//end for mb...

	/// If the final macroblocks of the slice were all skipped then a skip run must be coded onto the stream.
	if (_mb_skip_run)
	{
		if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			bitCount = _pHeaderUnsignedVlcEnc->Encode(_mb_skip_run);
			if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
				goto H264V2_VLCERROR_WRITE;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE;
			if (bsw)
				bsw->Write(bitCount, _pHeaderUnsignedVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;
		}//end if !I_Slice...
	}//end if _mb_skip_run...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE:
	_errorStr = "H264V2:[WriteSliceDataLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteSliceDataLayer.

/** Read the slice data layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int mb, i;
	int bitsUsedSoFar = 0;
	int numBits;

	/// Whip through each macroblock. Extract the encoded macroblock
	/// from the bit stream and vlc decode the vectors and coeff's.
	int len = _mbLength;
	_mb_skip_run = 0;

	/// Get the first skip run from the stream for P slices.
	if ((_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
		(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
	{
		_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
		numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
		if (numBits == 0)	///< Return = 0 implies no valid vlc code.
			goto H264V2_NOVLC_READ;
		bitsUsedSoFar += numBits;
		/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
		if (bitsUsedSoFar > remainingBits)
			goto H264V2_RUNOUTOFBITS_READ;
	}//end if !I_Slice...

	for (mb = 0; mb < len; mb++)
	{
		/// Short cut variables.
		MacroBlockH264* pMb = &(_pMb[mb]);

		/// --------------- Decode the macroblock header from the stream ----------------------

		if (_mb_skip_run && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All))
		{
			pMb->_skip = 1;
			_mb_skip_run--;

			/// Skip implies a P_Skip macroblock type as Inter_16x16.
			pMb->_intraFlag = 0;
			pMb->_mb_type = MacroBlockH264::Inter_16x16;
			pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;
			/// Skip implies a single 16x16 (0,0) motion vector difference.
			pMb->_mvdX[MacroBlockH264::_16x16] = 0;
			pMb->_mvdY[MacroBlockH264::_16x16] = 0;
			/// Set the motion vector to the predicted value.
			if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
			{
				/// Force to zero.
				pMb->_mvX[MacroBlockH264::_16x16] = 0;
				pMb->_mvY[MacroBlockH264::_16x16] = 0;
			}//end if SkippedZeroMotionPredCondition...
			else
				pMb->GetMbMotionMedianPred(pMb, &(pMb->_mvX[MacroBlockH264::_16x16]), &(pMb->_mvY[MacroBlockH264::_16x16]));
			pMb->_coded_blk_pattern = 0;
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (i = 0; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _mb_skip_run...
		else
		{
			/// Macroblock not skipped and header must be extracted.
			pMb->_skip = 0;

			/// Macroblock type.
			_pMb[mb]._mb_type = _pMbTypeVlcDec->Decode(bsr);
			numBits = _pMbTypeVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
			/// Unpack _intraFlag and _mbPartPredMode from the decoded _mb_type.
			_pMb[mb].UnpackMbType(&(_pMb[mb]), _slice._type);

			/// Intra requires lum and chr prediction modes, Inter requires reference 
			/// index lists and motion vector diff values.
			if (!_pMb[mb]._intraFlag)	///< Inter	(most common option)
			{
				int numOfVecs = 1;
				// TODO: Implement other partition modes.
				if (_pMb[mb]._mbPartPredMode == MacroBlockH264::Inter_16x16)
					numOfVecs = 1;
				else
					goto H264V2_NOMODE_READ;
				for (int vec = 0; vec < numOfVecs; vec++)
				{
					/// Get the motion vector differences for this macroblock.
					_pMb[mb]._mvdX[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;

					_pMb[mb]._mvdY[vec] = _pMbMotionVecDiffVlcDec->Decode(bsr);
					numBits = _pMbMotionVecDiffVlcDec->GetNumDecodedBits();
					if (numBits == 0)
						goto H264V2_NOVLC_READ;
					bitsUsedSoFar += numBits;
					if (bitsUsedSoFar > remainingBits)
						goto H264V2_RUNOUTOFBITS_READ;

					/// Get the prediction vector from the neighbourhood.
					int predX, predY;
					_pMb[mb].GetMbMotionMedianPred(&(_pMb[mb]), &predX, &predY);
					_pMb[mb]._mvX[vec] = predX + _pMb[mb]._mvdX[vec];
					_pMb[mb]._mvY[vec] = predY + _pMb[mb]._mvdY[vec];
				}//end for vec...
			}//end if !_interFlag...
			else											/// Intra
			{
				// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

				/// Get chr prediction mode.
				_pMb[mb]._intraChrPredMode = _pMbIChrPredModeVlcDec->Decode(bsr);
				numBits = _pMbIChrPredModeVlcDec->GetNumDecodedBits();
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end else...

			/// If not Intra_16x16 mode then _coded_blk_pattern must be extracted.
			if ((_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!_pMb[mb]._intraFlag))
			{
				/// Block coded pattern.
				int isInter = 1;
				if (_pMb[mb]._intraFlag) isInter = 0;
				numBits = _pBlkPattVlcDec->Decode2(bsr, &(_pMb[mb]._coded_blk_pattern), &isInter);
				if (numBits == 0)
					goto H264V2_NOVLC_READ;
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if !Intra_16x16...

		}//end else not skipped...

		/// Disassemble the bit pattern to determine which blocks are to be decoded.
		_pMb[mb].GetCodedBlockPattern(&(_pMb[mb]));

		/// For Inter modes and non-Intra_16x16 modes, delta qp is read only if there is at least one block 
		/// that has coeffs. The all zero coeff condition still requires the pattern to be decoded such that 
		/// zeros are loaded into the blocks.
		_pMb[mb]._mb_qp_delta = 0;	///< Default value required.
		if ((_pMb[mb]._coded_blk_pattern > 0) || (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16)))
		{
			/// Delta QP.
			_pMb[mb]._mb_qp_delta = _pDeltaQPVlcDec->Decode(bsr);
			numBits = _pDeltaQPVlcDec->GetNumDecodedBits();
			if (numBits == 0)
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if _coded_blk_pattern...

		int prevMbIdx = _pMb[mb]._mbIndex - 1;
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (_pMb[mb]._slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				_pMb[mb]._mbQP = _pMb[prevMbIdx]._mbQP + _pMb[mb]._mb_qp_delta;
			else
				_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;
		}//end if prevMbIdx...
		else
			_pMb[mb]._mbQP = _slice._qp + _pMb[mb]._mb_qp_delta;

		/// ------------------- Get the macroblock coeffs from the coded stream ---------------------
		int dcSkip = 0;
		int startBlk = 1;
		if (_pMb[mb]._intraFlag && (_pMb[mb]._mbPartPredMode == MacroBlockH264::Intra_16x16))
		{
			startBlk = 0;	///< Change starting block to include block num = -1;
			dcSkip = 1;
		}//end if Intra_16x16...
		/// For Lum blocks that are Inter coded and not Intra_16x16 coded the DC coeff is not skipped.
		for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
			_pMb[mb]._blkParam[i].dcSkipFlag = dcSkip;

		for (i = startBlk; i < MBH264_NUM_BLKS; i++)
		{
			/// Simplify the block reference.
			BlockH264* pBlk = _pMb[mb]._blkParam[i].pBlk;

			if (pBlk->IsCoded())
			{
				/// Choose the appropriate dimension CAVLC codec.
				IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
				if ((pBlk->GetHeight() == 4) && (pBlk->GetWidth() == 4))
					pCAVLC = _pCAVLC4x4;

				/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
				/// MB decodings in decoding order have already set the num of neighbourhood coeffs.
				int neighCoeffs = 0;
				if (_pMb[mb]._blkParam[i].neighbourIndicator)
				{
					if (_pMb[mb]._blkParam[i].neighbourIndicator > 0)
						neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pBlk);
					else	///< Negative values for neighbourIndicator imply pass through.
						neighCoeffs = _pMb[mb]._blkParam[i].neighbourIndicator;
				}//end if neighbourIndicator...
				pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
				pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, _pMb[mb]._blkParam[i].dcSkipFlag);

				numBits = pBlk->RleDecode(pCAVLC, bsr);					///< Vlc decode from the stream.
				if (numBits <= 0)	///< Vlc codec errors are detected from a negative return value.
				{
					if (numBits == -2)
						goto H264V2_RUNOUTOFBITS_READ;
					goto H264V2_NOVLC_READ;
				}//end if numBits...
				bitsUsedSoFar += numBits;
				if (bitsUsedSoFar > remainingBits)
					goto H264V2_RUNOUTOFBITS_READ;
			}//end if IsCoded()...
			else
			{
				pBlk->SetNumCoeffs(0);	///< For future use.
				pBlk->Zero();
			}//end else...
		}//end for i...

		/// If end of skipped macroblocks then get the next skip run from the stream.
		if (!_mb_skip_run && !pMb->_skip && (_slice._type != SliceHeaderH264::I_Slice) && (_slice._type != SliceHeaderH264::SI_Slice) &&
			(_slice._type != SliceHeaderH264::I_Slice_All) && (_slice._type != SliceHeaderH264::SI_Slice_All) && (mb != (len - 1)))
		{
			_mb_skip_run = _pHeaderUnsignedVlcDec->Decode(bsr);
			numBits = _pHeaderUnsignedVlcDec->GetNumDecodedBits();
			if (numBits == 0)	///< Return = 0 implies no valid vlc code.
				goto H264V2_NOVLC_READ;
			bitsUsedSoFar += numBits;
			/// Vlc length unknown and so only checked after the fact but assumes non-destructive read.
			if (bitsUsedSoFar > remainingBits)
				goto H264V2_RUNOUTOFBITS_READ;
		}//end if !_mb_skip_run...

	}//end for mb...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Insufficient bits to decode the picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_NOVLC_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] No valid vlc in bit stream";
	*bitsUsed = bitsUsedSoFar;
	return(2);

H264V2_NOMODE_READ:
	_errorStr = "H264V2:[ReadSliceDataLayer] Mode not supported";
	*bitsUsed = bitsUsedSoFar;
	return(3);
}//end ReadSliceDataLayer.

/** Write the macroblock layer to the global bit stream.
The encodings of all the macroblocks must be correctly defined before
this method is called. The vlc encoding is performed first before
writing. This impementation writes one non-skipped macroblock encoding.
Each write checks if a bit overflow will occur before writing. The check
is sufficiently frequent to warrant an early exit GOTO statement. If the
input stream param is NULL then this method is used to count the bits only.
@param bsw					: Stream to write into.
@param pMb					: Macroblock to encode.
@param allowedBits	: Upper limit to the writable bits.
@param bitsUsed			: Return the actual bits used.
@return							: Run out of bits = 1, more bits available = 0, Vlc error = 2.
*/
int H264v2Codec::WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed)
{
	int	bitCount, i;
	int bitsUsedSoFar = 0;
	int dcSkip = 0;
	int startBlk = 1;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitCount = _pMbTypeVlcEnc->Encode(pMb->_mb_type);
	if (bitCount <= 0)	///< Vlc codec errors are detected from a zero or negative return value.
		goto H264V2_VLCERROR_WRITE_MB;
	if ((bitsUsedSoFar + bitCount) > allowedBits)
		goto H264V2_RUNOUTOFBITS_WRITE_MB;
	if (bsw)
		bsw->Write(bitCount, _pMbTypeVlcEnc->GetCode());
	bitsUsedSoFar += bitCount;

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

			bitCount = _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
			if (bitCount <= 0)
				goto H264V2_VLCERROR_WRITE_MB;
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			if (bsw)
				bsw->Write(bitCount, _pMbMotionVecDiffVlcEnc->GetCode());
			bitsUsedSoFar += bitCount;

		}//end for vec...
	}//end if !_intraFlag...
	else											/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitCount = _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pMbIChrPredModeVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitCount = _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pBlkPattVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitCount = _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
		if (bitCount <= 0)
			goto H264V2_VLCERROR_WRITE_MB;
		if ((bitsUsedSoFar + bitCount) > allowedBits)
			goto H264V2_RUNOUTOFBITS_WRITE_MB;
		if (bsw)
			bsw->Write(bitCount, _pDeltaQPVlcEnc->GetCode());
		bitsUsedSoFar += bitCount;

	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitCount = (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, bsw);
			if (bitCount <= 0)
			{
				if (bitCount == -2)
					goto H264V2_RUNOUTOFBITS_WRITE_MB;
				goto H264V2_VLCERROR_WRITE_MB;
			}//end if bitCount...
			if ((bitsUsedSoFar + bitCount) > allowedBits)
				goto H264V2_RUNOUTOFBITS_WRITE_MB;
			bitsUsedSoFar += bitCount;
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	*bitsUsed = bitsUsedSoFar;
	return(0);

H264V2_RUNOUTOFBITS_WRITE_MB:
	/// Error info has contents loaded from outside of this method therefore concat is required.
	//strcat(_errorInfo, " H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture");
	//_errorStr = _errorInfo;
	_errorStr = "H264V2:[WriteMacroBlockLayer] Bits required exceeds max available for picture";
	*bitsUsed = bitsUsedSoFar;
	return(1);

H264V2_VLCERROR_WRITE_MB:
	_errorStr = "H264V2:[WriteMacroBlockLayer] Vlc encoder error";
	*bitsUsed = bitsUsedSoFar;
	return(2);

}//end WriteMacroBlockLayer.

/** Count the bits required to encode the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding. NB: No errors are checked.
@param pMb					: Macroblock to encode.
@return							: Total bit count.
*/
int H264v2Codec::MacroBlockLayerBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Map
	/// to the required H.264 coding order of each block when writing to the stream.

	/// ------------------------ Code the macroblock header -----------------------------------

	/// Macroblock type.
	bitsUsedSoFar = _pMbTypeVlcEnc->Encode(pMb->_mb_type);

	/// Intra requires lum and chr prediction modes, Inter requires reference 
	/// index lists and motion vector diff values.
	if (!pMb->_intraFlag)	/// Inter	(most common option)
	{
		int numOfVecs = 1;
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			numOfVecs = 1;
		for (int vec = 0; vec < numOfVecs; vec++)
		{
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdX[vec]);
			bitsUsedSoFar += _pMbMotionVecDiffVlcEnc->Encode(pMb->_mvdY[vec]);
		}//end for vec...
	}//end if !_intraFlag...
	else									/// Intra
	{
		// TODO: Implement Intra_8x8 and Intra_4x4 mode options.

		/// Write chr prediction mode.
		bitsUsedSoFar += _pMbIChrPredModeVlcEnc->Encode(pMb->_intraChrPredMode);
	}//end else...

	/// If not Intra_16x16 mode then _coded_blk_pattern must be written.
	if ((pMb->_intraFlag && (pMb->_mbPartPredMode != MacroBlockH264::Intra_16x16)) || (!pMb->_intraFlag))
	{
		/// Block coded pattern.
		int isInter = 1;
		if (pMb->_intraFlag) isInter = 0;
		bitsUsedSoFar += _pBlkPattVlcEnc->Encode2(pMb->_coded_blk_pattern, isInter);
	}//end if !Intra_16x16...

	/// For Inter modes and non-Intra_16x16 modes, delta qp and the residual coeffs are written only if 
	/// there is at least one block that has coeffs. 
	if ((pMb->_coded_blk_pattern > 0) || (pMb->_intraFlag && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)))
	{
		/// Delta QP.
		bitsUsedSoFar += _pDeltaQPVlcEnc->Encode(pMb->_mb_qp_delta);
	}//end if _coded_blk_pattern...

	/// ------------------ Code the macroblock data --------------------------------------------------------
	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...
	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and add to stream. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerBitCounter.

/** Count the bits required to encode the coeffs at the macroblock layer.
The encodings of all the macroblocks must be correctly defined before
this method is called. This impementation counts the bits required for
one non-skipped macroblock encoding excluding the headers. NB: No errors
are checked.
@param pMb	: Macroblock to encode.
@return			: Total bit count.
*/
int H264v2Codec::MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb)
{
	int	i;
	int bitsUsedSoFar = 0;

	/// Encode the vlc blocks with the context of the neighborhood number of coeffs. Ignore
  /// the header.

	int dcSkip = 0;
	int startBlk = 1;
	if ((pMb->_intraFlag) && (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16))
	{
		startBlk = 0;	///< Change starting block to include block num = -1;
		dcSkip = 1;
	}//end if Intra_16x16...

	/// For Lum blocks that are Inter coded or not Intra_16x16 coded, the DC coeff is not skipped.
	for (i = MBH264_LUM_0_0; i <= MBH264_LUM_3_3; i++)
		pMb->_blkParam[i].dcSkipFlag = dcSkip;

	for (i = startBlk; i < MBH264_NUM_BLKS; i++)
	{
		/// Simplify the block reference.
		BlockH264* pBlk = pMb->_blkParam[i].pBlk;

		if (pMb->_blkParam[i].pBlk->IsCoded())
		{
			/// Choose the appropriate dimension CAVLC codec. Only 4x4 or 2x2 are expected here.
			IContextAwareRunLevelCodec* pCAVLC = _pCAVLC2x2;
			if (((pMb->_blkParam[i].pBlk)->GetHeight() == 4) && ((pMb->_blkParam[i].pBlk)->GetWidth() == 4))
				pCAVLC = _pCAVLC4x4;

			/// Get num of neighbourhood coeffs as average of above and left block coeffs. Previous
			/// MB encodings in raster order have already set the num of coeffs.
			int neighCoeffs = 0;
			if (pMb->_blkParam[i].neighbourIndicator)
			{
				if (pMb->_blkParam[i].neighbourIndicator > 0)
					neighCoeffs = BlockH264::GetNumNeighbourCoeffs(pMb->_blkParam[i].pBlk);
				else	///< Negative values for neighbourIndicator imply pass through.
					neighCoeffs = pMb->_blkParam[i].neighbourIndicator;
			}//end if neighbourIndicator...
			pCAVLC->SetParameter(pCAVLC->NUM_TOT_NEIGHBOR_COEFF_ID, neighCoeffs);	///< Prepare the vlc coder.
			pCAVLC->SetParameter(pCAVLC->DC_SKIP_FLAG_ID, pMb->_blkParam[i].dcSkipFlag);

			///< Vlc encode and accumulate the bit count. The number of coeffs is set here for the blk.
			bitsUsedSoFar += (pMb->_blkParam[i].pBlk)->RleEncode(pCAVLC, NULL);
		}//end if IsCoded()...
		else
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);	///< For future use.
	}//end for i...

	return(bitsUsedSoFar);
}//end MacroBlockLayerCoeffBitCounter.

/** Read the macroblock layer from the global bit stream.
This impementation reads every macroblock encoding in top-left to
bottom-right order. Each read checks if a bit underflow will occur
after reading. Check for loss of vlc sync wherever possible. The
checks are sufficiently frequent to warrant an early exit GOTO
statement.
@param bsr						: Stream to read from.
@param remainingBits	: Upper limit to the readable bits.
@param bitsUsed				: Return the actual bits extracted.
@return								: Run out of bits = 1, more bits available = 0, error = 2.
*/
int H264v2Codec::ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed)
{
	int bitsUsedSoFar = 0;

	*bitsUsed = bitsUsedSoFar;
	return(0);
}//end ReadMacroBlockLayer.

/** Apply the in-loop edge filter.
Used in both the encoder and decoder to remove blocking artefacts on the 4x4 boundary
edges. It is applied macroblock by macroblock in raster scan order to the reference
images of both the Lum and Chr components.
@return	:	none.
*/
void H264v2Codec::ApplyLoopFilter(void)
{
	int mb, i, j;
	short** lumRef = _RefLum->Get2DSrcPtr();	///< Image space to operate on.
	short** cbRef = _RefCb->Get2DSrcPtr();
	short** crRef = _RefCr->Get2DSrcPtr();

	for (mb = 0; mb < _mbLength; mb++)
	{
		MacroBlockH264* pMb = &(_pMb[mb]);
		MacroBlockH264* aboveMb = _pMb[mb]._aboveMb;
		MacroBlockH264* leftMb = _pMb[mb]._leftMb;

		/// All macroblock boundaries that have intra neighbours use
		/// boundary strength = {3, 4}. Vertical filtering first.

		///---------------- Vertical Edges --------------------------------------
		if (leftMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || leftMb->_intraFlag)	///< Left intra macroblock boundary (bS = 4).
			{
				for (i = 0; i < 16; i += 4)
					VerticalFilter(pMb, lumRef, 1, i, 0, 4, 4);
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, 0, 4, 4);
					VerticalFilter(pMb, crRef, 0, i, 0, 4, 4);
				}//end for i...
			}//end if _intraFlag...
			else																	///< Left inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 vector is used
				// per macroblock and from the same single reference. Boundary 4x4 blocks 
		// are compared with the neighbouring macroblock motion vectors.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - leftMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - leftMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (i = 0; i < 4; i++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[i][0].GetNumCoeffs() || pMb->_lumBlk[i][0]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, 0, 4, bS);	///< At (row = 4*i, col = 0) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						VerticalFilter(pMb, cbRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
						VerticalFilter(pMb, crRef, 0, i << 1, 0, 2, bS);	///< At (row = 2*i, col = 0) do iter = 2 rows.
					}//end if bS...
				}//end for i...

			}//end else...
		}//end if leftMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (j = 4; j < 16; j += 4)
				for (i = 0; i < 16; i += 4)	///< All rows first for each col.
					VerticalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (j = 4; j < 8; j += 4)
				for (i = 0; i < 8; i += 4)
				{
					VerticalFilter(pMb, cbRef, 0, i, j, 4, 3);
					VerticalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for j & i...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (j = 1; j < 4; j++)
				for (i = 0; i < 4; i++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkLeft->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						VerticalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 rows.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (j == 2)
						{
							VerticalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
							VerticalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 rows.
						}//end if j...
					}//end if bS...

				}//end for j & i...
		}//end else...

		///---------------- Horizontal Edges -------------------------------------
		if (aboveMb != NULL)	///< Only look at macroblock boundary if there is a neighbour.
		{
			if (pMb->_intraFlag || aboveMb->_intraFlag)	///< Above intra macroblock boundary. (bS = 4)
			{
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, 0, j, 4, 4);
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, 0, j, 4, 4);
					HorizontalFilter(pMb, crRef, 0, 0, j, 4, 4);
				}//end for j...
			}//end if _intraFlag...
			else																	///< Above inter macroblock boundary.
			{
				// TODO: For this current implementation only one 16x16 motion vector is used
				// per macroblock and from the same single reference.

				int mvDiffersBy4 = 0;	///< Differ with neighbour by 4 quarter pel values.
				if ((H264V2_FAST_ABS32(pMb->_mvX[0] - aboveMb->_mvX[0]) >= 4) || (H264V2_FAST_ABS32(pMb->_mvY[0] - aboveMb->_mvY[0]) >= 4))
					mvDiffersBy4 = 1;

				for (j = 0; j < 4; j++)
				{
					int bS = mvDiffersBy4;
					if (pMb->_lumBlk[0][j].GetNumCoeffs() || pMb->_lumBlk[0][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this macroblock block boundary.
						HorizontalFilter(pMb, lumRef, 1, 0, j << 2, 4, bS);	///< At (row = 0, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						HorizontalFilter(pMb, cbRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
						HorizontalFilter(pMb, crRef, 0, 0, j << 1, 2, bS);	///< At (row = 0, col = 2*j) do iter = 2 cols.
					}//end if bS...
				}//end for j...

			}//end else...
		}//end aboveMb...

		if (pMb->_intraFlag)	///< Internal intra block edges.
		{
			for (i = 4; i < 16; i += 4)
				for (j = 0; j < 16; j += 4)
					HorizontalFilter(pMb, lumRef, 1, i, j, 4, 3);
			for (i = 4; i < 8; i += 4)
				for (j = 0; j < 8; j += 4)
				{
					HorizontalFilter(pMb, cbRef, 0, i, j, 4, 3);
					HorizontalFilter(pMb, crRef, 0, i, j, 4, 3);
				}//end for i & j...
		}//end if _intraFlag...
		else										///< Internal inter block edges.
		{
			// TODO: For this current implementation only one 16x16 motion vector is used
			// per macroblock and from the same single reference. Therefore all internal
			// blocks have the same motion vector i.e. difference = 0.

			for (i = 1; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					int bS = 0;
					if (pMb->_lumBlk[i][j].GetNumCoeffs() || pMb->_lumBlk[i][j]._blkAbove->GetNumCoeffs())	///< Coded coeffs in block with q or block with p.
						bS = 2;

					if (bS)
					{
						/// Apply the filter to this block boundary.
						HorizontalFilter(pMb, lumRef, 1, i << 2, j << 2, 4, bS);	///< At (row = 4*i, col = 4*j) do iter = 4 cols.

						/// Apply to the aligned chr edge assuming 4:2:0 here only.
						if (i == 2)
						{
							HorizontalFilter(pMb, cbRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
							HorizontalFilter(pMb, crRef, 0, i << 1, j << 1, 2, bS);	///< At (row = 2*i, col = 2*j) do iter = 2 cols.
						}//end if i...
					}//end if bS...

				}//end for i & j...
		}//end else...

	}//end for mb...

}//end ApplyLoopFilter.

/** Apply the in-loop deblocking filter to vertical block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one column with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations down the col from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + pMb->_leftMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_leftMb != NULL) && (colOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_leftMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY + i][offX - 1] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY + i][offX] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX - 2] = (short)(p1 + delta);		                ///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + i][offX + 1] = (short)(q1 + delta);		                ///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be colOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate down the column.
		{
			int p1 = (int)(img[offY + i][offX - 2]);
			int p0 = (int)(img[offY + i][offX - 1]);
			int q0 = (int)(img[offY + i][offX]);
			int q1 = (int)(img[offY + i][offX + 1]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY + i][offX - 3]);
				int q2 = (int)(img[offY + i][offX + 2]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX - 1] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY + i][offX - 2] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY + i][offX - 3] = (short)(((2 * (int)(img[offY + i][offX - 4])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX - 1] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY + i][offX] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + i][offX + 1] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + i][offX + 2] = (short)(((2 * (int)(img[offY + i][offX + 3])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY + i][offX] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end VerticalFilter.

/** Apply the in-loop deblocking filter to horizontal block edges.
The deblocking filter is applied only after the image has been fully
decoded. This method operates on one row with the given boundary
strength. The operation is defined in the ITU-T Recommendation
H.264 (03/2005).
@param pMb							: Macroblock to operate on.
@param img							: Reference image to filter.
@param lumFlag					: Indicates the colour component of the ref image.
@param rowOff						: The row offset within the macroblock with the top-left corner as (0,0).
@param colOff						: The column offset.
@param iter							: Iterations along the row from (rowOff, colOff).
@param boundaryStrength	: Boundary strength to apply.
@return									: none
*/
void H264v2Codec::HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength)
{
	int i;
	int qPav, offX, offY;
	if (lumFlag)
	{
		qPav = pMb->_mbQP;
		/// Modify to average qP with the neighbour if this is a mb edge.
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + pMb->_aboveMb->_mbQP + 1) >> 1;
		offX = pMb->_offLumX + colOff;
		offY = pMb->_offLumY + rowOff;
	}//end if lumFlag...
	else
	{
		qPav = MacroBlockH264::GetQPc(pMb->_mbQP);
		if ((pMb->_aboveMb != NULL) && (rowOff == 0))
			qPav = (qPav + MacroBlockH264::GetQPc(pMb->_aboveMb->_mbQP) + 1) >> 1;
		offX = pMb->_offChrX + colOff;
		offY = pMb->_offChrY + rowOff;
	}//end else...

	switch (boundaryStrength)
	{
	case 1:
	case 2:
	case 3:
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				int delta = (((q0 - p0) << 2) + (p1 - q1) + 4) >> 3;
				int tC0 = indexAbS[boundaryStrength - 1][qPav];
				int tC;
				if (lumFlag)
					tC = tC0 + ((H264V2_FAST_ABS32((p2 - p0)) < b) ? 1 : 0) + ((H264V2_FAST_ABS32((q2 - q0)) < b) ? 1 : 0);
				else
					tC = tC0 + 1;
				if (delta < -tC)	delta = -tC;
				else if (delta > tC)	delta = tC;

				img[offY - 1][offX + i] = (short)(H264V2_CLIP255(p0 + delta));			///< p0.
				img[offY][offX + i] = (short)(H264V2_CLIP255(q0 - delta));			///< q0.

				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && lumFlag)
				{
					delta = (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY - 2][offX + i] = (short)(p1 + delta);			///< p1.
				}//end if abs(p2)...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && lumFlag)
				{
					delta = (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1;
					if (delta < -tC0)	delta = -tC0;
					else if (delta > tC0)	delta = tC0;

					img[offY + 1][offX + i] = (short)(q1 + delta);			///< q1.
				}//end if abs(q2)...
			}//end if abs(p0)...
		}//end for i...
		break;
	}//end case 1,2 & 3...
	case 4:	///< This bS = 4 only occurs for intra boundaries and therefore must be rowOff = 0;.
	{
		int a = H264v2Codec::alpha[qPav];
		int b = H264v2Codec::beta[qPav];

		for (i = 0; i < iter; i++)	///< Iterate along the row.
		{
			int p1 = (int)(img[offY - 2][offX + i]);
			int p0 = (int)(img[offY - 1][offX + i]);
			int q0 = (int)(img[offY][offX + i]);
			int q1 = (int)(img[offY + 1][offX + i]);
			/// Test boundary differences to switch the filtering on/off.
			if ((H264V2_FAST_ABS32((p0 - q0)) < a) && (H264V2_FAST_ABS32((p1 - p0)) < b) && (H264V2_FAST_ABS32((q1 - q0)) < b))
			{
				int p2 = (int)(img[offY - 3][offX + i]);
				int q2 = (int)(img[offY + 2][offX + i]);
				if ((H264V2_FAST_ABS32((p2 - p0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY - 1][offX + i] = (short)((p2 + (2 * p1) + (2 * p0) + (2 * q0) + q1 + 4) >> 3);														///< p0.
					img[offY - 2][offX + i] = (short)((p2 + p1 + p0 + q0 + 2) >> 2);																						///< p1.
					img[offY - 3][offX + i] = (short)(((2 * (int)(img[offY - 4][offX + i])) + (3 * p2) + p1 + p0 + q0 + 4) >> 3);		///< p2.
				}//end if abs(p2)...
				else
				{
					img[offY - 1][offX + i] = (short)(((2 * p1) + p0 + q1 + 2) >> 2);																							///< p0.
				}//end else...

				if ((H264V2_FAST_ABS32((q2 - q0)) < b) && (H264V2_FAST_ABS32((p0 - q0)) < ((a >> 2) + 2)) && lumFlag)
				{
					img[offY][offX + i] = (short)((p1 + (2 * p0) + (2 * q0) + (2 * q1) + q2 + 4) >> 3);														///< q0.
					img[offY + 1][offX + i] = (short)((p0 + q0 + q1 + q2 + 2) >> 2);																						///< q1.
					img[offY + 2][offX + i] = (short)(((2 * (int)(img[offY + 3][offX + i])) + (3 * q2) + q1 + q0 + p0 + 4) >> 3);		///< q2.
				}//end if abs(p2)...
				else
				{
					img[offY][offX + i] = (short)(((2 * q1) + q0 + p1 + 2) >> 2);																									///< q0.
				}//end else...
			}//end if abs(p0)...
		}//end for i...

		break;
	}//end case 4...
	}//end switch boundaryStrength...

}//end HorizontalFilter.

/** Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		short*			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i]);	///< Short cuts.
		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);

		/// Transform without scaling or quant.
		_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][0]
		*pDcLumBlk++ = pLumBlk->GetDC(); ///< Set the Lum DC block from the DC term of this block and scale it without rounding.
		(pLumBlk++)->SetDC(0); ///< Required to ensure the feedback loop operates properly.

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][1]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][2]
		*pDcLumBlk++ = pLumBlk->GetDC();
		(pLumBlk++)->SetDC(0);

		pLumBlk->ForwardTransform(_pF4x4TLum);	///< [i][3]
		*pDcLumBlk = pLumBlk->GetDC();
		pLumBlk->SetDC(0);

		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][3]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][2]
		(pLumBlk--)->Quantise(_pF4x4TLum);	///< [i][1]
		pLumBlk->Quantise(_pF4x4TLum);			///< [i][0]
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantIntra16x16MBlk.

/** Transform and Quantise an Intra_16x16 macroblock to below a max distortion criterion.
This overload method decrements the mb QP value from its existing value until the mb distortion
drops below the specified Dmax value. It returns the distortion at the final value of QP that
meets the criterion and places the decoded mb values in the temp blks. The final inverse decoded
blks are stored in the tmp blks.
@param pMb	  : Macroblock to transform.
@param Dmax   : Target max distortion criterion.
@param minQP  : Lowest QP value allowed.
@return			  : Lum distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int qp = pMb->_mbQP;
	int distortion = 0;

	///------------ Lum in raster scan order--------------------------

	  /// Transform without quant to extract the DC term. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);

			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);   ///< DCT.
			*pDcLumBlk++ = pb->GetDC();         ///< Set DC blk
			pb->SetDC(0);                       ///< Clear DC term in AC blk.
		}//end for i & j...

		/// Transform the DC blocks.
	_pFDC4x4T->SetMode(IForwardTransform::TransformOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	/// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);
		_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			}//end for i & j...

			/// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

		/// For QP = H264V2_MAX_QP it is likely that all coeffs are zeros. Find the QP value 
		/// that results in at least 1 non-zero coeff.
	//    if(qp == H264V2_MAX_QP)
	//      qp = GetQPtoNonZeroCoeff(pMb, minQP);

		/// Inverse quant and inverse transform the DC blks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

		/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
		distortion = 0;
		short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to DC blk.
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
				pb->InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
				pb->SetDC(*pDcLumBlkTmp++);       ///< Load the DC term from the DC blk.

				_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
				pb->InverseTransform(_pI4x4TLum); ///< Inverse transform.

				/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

		/// Update mb QP.
		pMb->_mbQP = qp;
		/// New qp.
		qp -= 4; //MbStepSize[qp];
		if (qp < minQP) qp = minQP;

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the main lum AC and DC blks.
	_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
		}//end for i & j...
	_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	///----------- Chr in raster scan order --------------------------

	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...

	  /// Restore state.
	_pFDC4x4T->SetMode(IForwardTransform::TransformAndQuant);
	pMb->_mbEncQP = pMb->_mbQP;

	return(distortion);
}//end TransAndQuantIntra16x16MBlk.

/** Code refactoring for TransAndQuantIntra16x16MBlk() method.
Get the mb QP value such that there is at least one non-zero DCT coeff.
@param pMb	  : Macroblock to transform.
@return       : QP value for non-zero coeffs.
*/
int H264v2Codec::GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP)
{
	int i, j;
	int qp = H264V2_MAX_QP;

	/// Are all coeffs zeros?
	int isZero = pMb->_lumDcBlkTmp.IsZero2();
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			isZero &= pMb->_lumBlkTmp[i][j].IsZero2();
	if (isZero)
	{
		/// Re-quant at QP = 1.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, 1);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, 1);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);

		/// Find the blk and position of the peak peak value.
		BlockH264*  pPeakBlk = &(pMb->_lumDcBlkTmp);
		short*      pB = pPeakBlk->GetBlk();
		int         peakPos = 0;
		short       peakVal = abs(pB[0]);

		for (i = 1; i < 16; i++) ///< DC blk.
		{
			if (abs(pB[i]) > peakVal)
			{
				peakPos = i;
				peakVal = abs(pB[i]);
			}//end if pB[]...
		}//end for i...

		for (i = 0; i < 4; i++)  /// AC blks.
			for (j = 0; j < 4; j++)
			{
				pB = pMb->_lumBlkTmp[i][j].GetBlk();
				for (int k = 0; k < 16; k++)
				{
					if (abs(pB[k]) > peakVal)
					{
						peakPos = k;
						peakVal = abs(pB[k]);
						pPeakBlk = &(pMb->_lumBlkTmp[i][j]);
					}//end if abs(pB[])...
				}//end for k...
			}//end for i & j...

		  /// Get the pre-quant value from the main blks in the position required.
		short val = (pPeakBlk->GetBlk())[peakPos];
		IForwardTransform* pQuantiser = _pF4x4TLum;
		if (pPeakBlk->IsDc())
			pQuantiser = _pFDC4x4T;

		/// Quantise this single peak value until it is non-zero.
		qp = H264V2_MAX_QP - 1;
		while ((qp > minQP) && (pQuantiser->QuantiseValue(val, peakPos, qp) == 0))
		{
			qp -= MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end while qp...

		/// Re-load and quantise the whole mb at this new QP value.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, qp);
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);
		/// Quant the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				pMb->_lumBlkTmp[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			  /// Quant the temp DC blocks.
		_pFDC4x4T->SetMode(IForwardTransform::QuantOnly);
		pMb->_lumDcBlkTmp.ForwardTransform(_pFDC4x4T);

	}//end if isZero...

	return(qp);
}//end SetQPtoNonZeroCoeff.

/** Transform and Quantise an Intra_16x16 macroblock with Inverse.
This method provides a speed improvement for macroblock processing and code refactoring. The
inverse transform and distortion measurment is included to the temp blks.
@param pMb	  : Macroblock to transform.
@param withD  : Include distortion calculation.
@return			  : distortion.
*/
int H264v2Codec::TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD)
{
	int i, j;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	int distortion = 0;

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method. The DC blocks are in the TransformAndQuant mode.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pFDC4x4T->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);

	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
  /// Copy the coeffs to the temp blks and do the inverse process.

  ///------------ Lum in raster scan order--------------------------

	short* pDcLumBlk = pMb->_lumDcBlk.GetBlk();  ///< Short cut to DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the pred images.
			if (withD)
				pMb->_lumBlk[i][j].Copy(_tmpBlk[i][j].GetBlk());

			_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
			pMb->_lumBlk[i][j].ForwardTransform(_pF4x4TLum);  ///< DCT.
			pDcLumBlk[i * 4 + j] = pMb->_lumBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_lumBlk[i][j].SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TLum->SetMode(IForwardTransform::QuantOnly); ///< Scale and quant.
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);

		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_lumDcBlk.ForwardTransform(_pFDC4x4T);

	/// Copy the Lum blks into the temp Lum blks for inverse transform + quant processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_DC, MBH264_LUM_3_3);

	/// Inverse quant and inverse transform the temp DC blks.
	pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);

	/// Inverse quant then add DC term before inverse transform. Accumulate distortion.
	short* pDcLumBlkTmp = pMb->_lumDcBlkTmp.GetBlk();  ///< Short cut to temp DC blk.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
			pMb->_lumBlkTmp[i][j].InverseQuantise(_pI4x4TLum);	///< Inverse scale and quant.
			pMb->_lumBlkTmp[i][j].SetDC(pDcLumBlkTmp[4 * i + j]); ///< Load the DC term from the DC blk.

			_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
			pMb->_lumBlkTmp[i][j].InverseTransform(_pI4x4TLum); ///< Inverse transform.

			/// Total square diff with the input store.
			if (withD)
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pMb->_lumBlkTmp[i][j].GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
		}//end for i & j...

  /// Region of interest multiplier application to the whole mb.
  distortion = ROIDistortion(pMb->_mbIndex, distortion);

  ///----------- Chr in raster scan order --------------------------

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pMb->_cbBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCbBlk[i * 2 + j] = pMb->_cbBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_cbBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			/// Cr
			pMb->_crBlk[i][j].ForwardTransform(_pF4x4TChr); ///< DCT.
			pDcCrBlk[i * 2 + j] = pMb->_crBlk[i][j].GetDC();  ///< Set DC blk
			pMb->_crBlk[i][j].SetDC(0);                     ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pMb->_cbBlk[i][j].Quantise(_pF4x4TChr);         ///< Scale and quant.
			pMb->_crBlk[i][j].Quantise(_pF4x4TChr);
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pMb->_cbBlkTmp[i][j].InverseQuantise(_pI4x4TChr); ///< Inverse scale and quant.
			pMb->_cbBlkTmp[i][j].SetDC(pDcCbBlkTmp[2 * i + j]); ///< Load the DC term from the DC blk.
			pMb->_crBlkTmp[i][j].InverseQuantise(_pI4x4TChr);
			pMb->_crBlkTmp[i][j].SetDC(pDcCrBlkTmp[2 * i + j]);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pMb->_cbBlkTmp[i][j].InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pMb->_crBlkTmp[i][j].InverseTransform(_pI4x4TChr);
		}//end for i & j...

	return(distortion);
}//end TransAndQuantIntra16x16MBlkWithInv.

/** Transform and Quantise an Intra_16x16 mode block.
Code refactoring method to transform the block and store the DC coeff before quantisation. The
transform must have the quantisation parameter preset before calling this method.
@param pTQ					: Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to store the DC coeff.
@return							: none.
*/
void H264v2Codec::TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IForwardTransform::TransformOnly);
	pBlk->ForwardTransform(pTQ);
	*pDcBlkCoeff = pBlk->GetDC();	///< Set the DC block from the DC term of this block.
	pBlk->SetDC(0);								///< Required to ensure the feedback loop operates properly.
	pTQ->SetMode(IForwardTransform::QuantOnly);
	pBlk->Quantise(pTQ);
}//end TransAndQuantIntra16x16ModeBlk.

/** Inverse Transform and Quantise an Intra_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pIDC4x4T->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks to temp blks.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, 0, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlkTmp.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_lumDcBlk.InverseTransform(_pIDC4x4T);
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		short*			pDcLumBlk;
		BlockH264*	pLumBlk;

		/// Unroll the inner loop.

		if (tmpBlkFlag)
		{
			pDcLumBlk = &((pMb->_lumDcBlkTmp.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlkTmp[i][0]);
		}//end if tmpBlkFlag...
		else
		{
			pDcLumBlk = &((pMb->_lumDcBlk.GetBlk())[4 * i + 3]);	///< Short cuts.
			pLumBlk = &(pMb->_lumBlk[i][0]);
		}//end else...

		/// Inverse scale and quant.
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
		_pI4x4TLum->SetMode(IInverseTransform::QuantOnly);
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseQuantise(_pI4x4TLum);	///< [i][2]
		pLumBlk->InverseQuantise(_pI4x4TLum);			///< [i][3]
		_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform without scaling or quant.
		_pI4x4TLum->SetMode(IInverseTransform::TransformOnly);
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);

		pLumBlk->SetDC(*pDcLumBlk--);						///< Load the DC term from the DC block.
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][3]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][2]

		pLumBlk->SetDC(*pDcLumBlk--);
		(pLumBlk--)->InverseTransform(_pI4x4TLum);	///< [i][1]

		pLumBlk->SetDC(*pDcLumBlk);
		pLumBlk->InverseTransform(_pI4x4TLum);			///< [i][0]

		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantIntra16x16MBlk.

/** Inverse Quantise and Transform an Intra_16x16 mode block.
Code refactoring method to inverse quantise the block and set the DC coeff before the inverse
transform. The inverse transform must have the quantisation parameter preset before calling
this method.
@param pTQ					: Inverse Transform to use.
@param pBlk					: Blk to process.
@param pDcBlkCoeff	: reference to get the DC coeff.
@return							: none.
*/
void H264v2Codec::InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff)
{
	pTQ->SetMode(IInverseTransform::QuantOnly);
	pBlk->InverseQuantise(pTQ);
	pBlk->SetDC(*pDcBlkCoeff);	///< Set the DC coeff for this block from the DC block.
	pTQ->SetMode(IInverseTransform::TransformOnly);
	pBlk->InverseTransform(pTQ);
}//end InvTransAndQuantIntra16x16ModeBlk.

/** Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb	: Macroblock to transform.
@return			: none
*/
void H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb)
{
	int i;
	int mbLumQP = pMb->_mbQP;
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the chr 4x4 AC blocks in this method. The lum and DC blocks are in the 
  /// TransformAndQuant mode and require the setting.
	_pF4x4TLum->SetMode(IForwardTransform::TransformAndQuant);
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, mbLumQP);
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);

	/// Do the forward 4x4 transform on the non-DC 4x4 blocks without scaling or quantisation. Pull
	/// out the DC terms from each chr block and populate the DC blocks and then scale and quant the
	/// non-DC 4x4 blocks. Note that this is done in raster scan order and not coding order to
	/// align each position in the DC block with the spatial location of the 4x4 block in the image.
	BlockH264*	pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
	BlockH264*	pCrBlk = &(pMb->_crBlk[0][0]);
	short*			pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short*			pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 4; i++)
	{
		/// Unroll the inner loop.

		BlockH264*	pLumBlk = &(pMb->_lumBlk[i][0]);	///< Short cuts.

		/// Transform Lum with scaling and quant.
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][0]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][1]
		(pLumBlk++)->ForwardTransform(_pF4x4TLum);	///< [i][2]
		pLumBlk->ForwardTransform(_pF4x4TLum);			///< [i][3]

	/// For chr, split the transform and quant processes. 
		_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);

		pCbBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCbBlk++ = pCbBlk->GetDC();
		pCbBlk->SetDC(0);

		pCrBlk->ForwardTransform(_pF4x4TChr);	///< [i]
		*pDcCrBlk++ = pCrBlk->GetDC();
		pCrBlk->SetDC(0);

		/// Now scale and quant chr.
		_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
		(pCbBlk++)->Quantise(_pF4x4TChr);
		(pCrBlk++)->Quantise(_pF4x4TChr);

	}//end for i...

	/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

}//end TransAndQuantInter16x16MBlk.

/** Transform and Quantise an Inter_16x16 macroblock with a Dmax criterion.
This method provides a speed improvement for macroblock processing and code refactoring. The
QP value is decremented until the mb Lum distortion is below Dmax. The quatised coeff are stored
in the _lumBlk[][], etc. and the inverse reconstructed pels are stored in the _lumBlkTmp[][], etc.
@param pMb	  : Macroblock to transform.
@param Dmax   : Max distortion for this mb.
@param minQP  : Lower limit for the QP descent.
@return			  : Distortion for the mb.
*/
int H264v2Codec::TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP)
{
	int i, j;
	int distortion = 0;
	int qp = pMb->_mbQP;
	int eqp = pMb->_mbEncQP;
	if (eqp > (H264V2_MAX_QP + 16))  ///< Only consider lum coeffs.
		eqp = H264V2_MAX_QP + 16;

	/// ----------------------------- Lum -----------------------------------------------------------
	/// Transform without quant and store. This is then used as the starting storage
	/// point to reload on each iteration of the Dmax descent. The main blks are only quantised 
	/// when the final QP value is determined.
	_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
	_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			BlockH264* pb = &(pMb->_lumBlk[i][j]);
			/// Make a copy of the input lum blks for later distortion calculations. These input
		  /// blks enter this method holding the diff between the input and the motion pred images.
			pb->Copy(_tmpBlk[i][j].GetBlk());
			/// DCT in-place but no quant.
			pb->ForwardTransform(_pF4x4TLum);
		}//end for i & j...

	  /// Iterate QP down from qp to either distortion <= Dmax or minQP (without distortion <= Dmax is best 
	  /// that can be done).
	do
	{
		/// Forward.
		_pF4x4TLum->SetParameter(IForwardTransform::QUANT_ID, qp);
		/// Inverse
		_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, qp);

		/// Copy the Lum blks into the temp Lum blks for forward quant and inverse transform + quant processing.
		MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_LUM_0_0, MBH264_LUM_3_3);

		/// Quant only for the temp Lum blks.
		_pF4x4TLum->SetMode(IForwardTransform::QuantOnly);
		/// Invese quant and transform.
		_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);

		/// Forward quant and inverse quant and transform. Accumulate distortion.
		distortion = 0;
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				BlockH264* pb = &(pMb->_lumBlkTmp[i][j]);

				pb->ForwardTransform(_pF4x4TLum); ///< Forward quant.
				/// For extended EncQP range [52..67], zero coeffs.
				if (eqp > H264V2_MAX_QP)
					pb->Zero(16 - (eqp - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);

				pb->InverseTransform(_pI4x4TLum);	///< Inverse scale, quant and transform.
			/// Total square diff with the input store.
#ifdef USE_ABSOLUTE_DIFFERENCE
				distortion += pb->GetBlkOverlay()->Tad4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#else
				distortion += pb->GetBlkOverlay()->Tsd4x4(*(_tmpBlk[i][j].GetBlkOverlay()));
#endif
			}//end for i & j...

    /// Region of interest multiplier application to the whole mb.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);

    /// Update mb QP.
		pMb->_mbQP = qp;
		pMb->_mbEncQP = eqp;
		/// New qp.
		if (eqp > H264V2_MAX_QP)
		{
			eqp -= 4;
			if (eqp < H264V2_MAX_QP) eqp = H264V2_MAX_QP;
		}//end if eqp...
		else
		{
			qp -= 4; //MbStepSize[qp];
			if (qp < minQP) qp = minQP;
		}//end else...

	} while ((qp > minQP) && (distortion > Dmax)); //end do while qp...

	/// Finally quant the lum blks.
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
		{
			pMb->_lumBlk[i][j].Quantise(_pF4x4TLum);        ///< Scale and quant.
			/// Zero coeffs for extended EncQP range.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
				pMb->_lumBlk[i][j].Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
		}//end for i & j...

	  /// ----------------------------- Chr -----------------------------------------------------------
	  /// Chr is processed after the QP value for this block has been determined by the Lum process.
	int mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);
	/// Forward.
	_pF4x4TChr->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	_pFDC2x2T->SetParameter(IForwardTransform::QUANT_ID, mbChrQP);
	/// Inverse.
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	short* pDcCbBlk = pMb->_cbDcBlk.GetBlk();
	short* pDcCrBlk = pMb->_crDcBlk.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCb = &(pMb->_cbBlk[i][j]);
			BlockH264*  pCr = &(pMb->_crBlk[i][j]);

			_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
			/// Cb
			pCb->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCbBlk++ = pCb->GetDC();         ///< Set DC blk
			pCb->SetDC(0);                      ///< Clear DC term in AC blk.

			/// Cr
			pCr->ForwardTransform(_pF4x4TChr);  ///< DCT.
			*pDcCrBlk++ = pCr->GetDC();         ///< Set DC blk
			pCr->SetDC(0);                      ///< Clear DC term in AC blk.

			_pF4x4TChr->SetMode(IForwardTransform::QuantOnly);
			pCb->Quantise(_pF4x4TChr);         ///< Scale and quant.
			pCr->Quantise(_pF4x4TChr);

			/// Follow the lum extended QP range on the Chr AC coeffs.
			if (pMb->_mbEncQP > H264V2_MAX_QP)
			{
				pCb->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
				pCr->Zero(16 - (pMb->_mbEncQP - H264V2_MAX_QP), CAVLCH264Impl::zigZag4x4Pos);
			}//end if _mbEncQP...
		}//end for i & j...

		/// Transform and quant the DC blocks.
	pMb->_cbDcBlk.ForwardTransform(_pFDC2x2T);
	pMb->_crDcBlk.ForwardTransform(_pFDC2x2T);

	/// Copy the Chr blks into the temp blks for inverse processing.
	MacroBlockH264::CopyBlksToTmpBlks(pMb, MBH264_CB_DC, MBH264_CR_1_1);

	/// Inverse quant and inverse transform the DC blks.
	pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
	pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

	/// Inverse quant then add DC term before inverse transform.
	short* pDcCbBlkTmp = pMb->_cbDcBlkTmp.GetBlk();
	short* pDcCrBlkTmp = pMb->_crDcBlkTmp.GetBlk();
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
		{
			BlockH264*  pCbT = &(pMb->_cbBlkTmp[i][j]);
			BlockH264*  pCrT = &(pMb->_crBlkTmp[i][j]);

			_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
			pCbT->InverseQuantise(_pI4x4TChr);  ///< Inverse scale and quant.
			pCbT->SetDC(*pDcCbBlkTmp++);        ///< Load the DC term from the DC blk.
			pCrT->InverseQuantise(_pI4x4TChr);
			pCrT->SetDC(*pDcCrBlkTmp++);

			_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
			pCbT->InverseTransform(_pI4x4TChr);  ///< Inverse transform.
			pCrT->InverseTransform(_pI4x4TChr);
		}//end for i & j...


	return(distortion);
}//end TransAndQuantInter16x16MBlk.

/** Inverse Transform and Quantise an Inter_16x16 macroblock
This method provides a speed improvement for macroblock processing and code refactoring.
@param pMb				: Macroblock to inverse transform.
@param tmpBlkFlag	: Indicate temp blocks to be used.
@return						: none
*/
void H264v2Codec::InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag)
{
	int					i;
	BlockH264*	pLumBlk;
	BlockH264*	pCbBlk;
	BlockH264*	pCrBlk;
	short*			pDcCbBlk;
	short*			pDcCrBlk;
	int					mbLumQP = pMb->_mbQP;
	int					mbChrQP = MacroBlockH264::GetQPc(pMb->_mbQP);

	/// The inverse transform (mode = TransformOnly) and quantisation (mode = QuantOnly) are separated 
	/// for the 4x4 AC blocks in this method and therefore the quant parameter does not need to 
	/// be set. But the DC blocks are in the TransformAndQuant mode and require the setting.
	_pI4x4TLum->SetMode(IInverseTransform::TransformAndQuant);
	_pI4x4TLum->SetParameter(IInverseTransform::QUANT_ID, mbLumQP);
	_pI4x4TChr->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);
	_pIDC2x2T->SetParameter(IInverseTransform::QUANT_ID, mbChrQP);

	if (tmpBlkFlag)
	{
		/// Copy all blks, excluding Lum DC blk, to temp blks.
		MacroBlockH264::CopyBlksToTmpBlksCoeffOnly(pMb, 1, MBH264_NUM_BLKS - 1);

		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlkTmp.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlkTmp.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Lum & Chr components.
		pLumBlk = &(pMb->_lumBlkTmp[0][0]);
		pCbBlk = &(pMb->_cbBlkTmp[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlkTmp[0][0]);
		pDcCbBlk = pMb->_cbDcBlkTmp.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlkTmp.GetBlk();
	}//end if tmpBlkFlag...
	else
	{
		/// Inverse transform & inverse quantise DC blocks.
		pMb->_cbDcBlk.InverseTransform(_pIDC2x2T);
		pMb->_crDcBlk.InverseTransform(_pIDC2x2T);

		/// Short cut pointers for Chr components.
		pLumBlk = &(pMb->_lumBlk[0][0]);
		pCbBlk = &(pMb->_cbBlk[0][0]);	///< Assume these are linear arrays that wrap in raster scan order.
		pCrBlk = &(pMb->_crBlk[0][0]);
		pDcCbBlk = pMb->_cbDcBlk.GetBlk();	///< Actual array of coeffs.
		pDcCrBlk = pMb->_crDcBlk.GetBlk();
	}//end else...

	/// Inverse quant for the main Lum, Cb and Cr blocks, insert the DC terms from the 
	/// DC blocks and then complete the inverse transform process. Note that this is 
	/// done in raster scan order and not coding order to align each position in the 
	/// DC block with the spatial location of the 4x4 block in the image.

	for (i = 0; i < 4; i++)	///< 16 Lum blocks + 4 Cb Chr and 4 Cr Chr blocks.
	{
		/// Unroll the inner loop.

		/// Inverse scale, quant and transform Lum.
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][0]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][1]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][2]
		(pLumBlk++)->InverseTransform(_pI4x4TLum);	///< [i][3]

	/// Inverse scale and quant first for Chr.
		_pI4x4TChr->SetMode(IInverseTransform::QuantOnly);
		pCbBlk->InverseQuantise(_pI4x4TChr);
		pCrBlk->InverseQuantise(_pI4x4TChr);

		/// Inverse transform after scaling and quant.
		_pI4x4TChr->SetMode(IInverseTransform::TransformOnly);
		pCbBlk->SetDC(*pDcCbBlk++);
		(pCbBlk++)->InverseTransform(_pI4x4TChr);	///< [i]

		pCrBlk->SetDC(*pDcCrBlk++);
		(pCrBlk++)->InverseTransform(_pI4x4TChr);	///< [i]
	}//end for i...

}//end InverseTransAndQuantInter16x16MBlk.

/** Get Intra Lum prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref lum img and write it to the pred parameter. Used by the encoder. Return the
intra_16x16 prediction mode.
@param pMb				: Macroblock to predict.
@param in					: Lum input image.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred)
{
	int i, j;
	int a, b, c;	///< Plane mode intermediates.
	int predDC;	///< Other mode intermediates.
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_16x16_DC;

	short**	in2D = in->Get2DSrcPtr();
	int			iOffX = in->GetOriginX();
	int			iOffY = in->GetOriginY();
	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Plane mode preparation --------------------------------------
		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
			V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
		}//end for i...
		b = (5 * H + 32) >> 6;
		c = (5 * V + 32) >> 6;
		a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_16x16_Plane] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], H264V2_CLIP255((a + b*(x - 7) + c*(y - 7) + 16) >> 5));
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
		predDC = (predDC + 16) >> 5;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		for (i = MacroBlockH264::Intra_16x16_Horiz; i < 3; i++)	///< Total of 3 modes. Plane mode excluded.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY + i][rOffX - 1];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Horiz mode.
			modeDist[MacroBlockH264::Intra_16x16_Horiz] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY + y][rOffX - 1]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Horiz;	///< MacroBlockH264::Intra_16x16_Horiz = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Horiz])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		predDC = 0;
		for (i = 0; i < 16; i++)
			predDC += (int)ref2D[rOffY - 1][rOffX + i];
		predDC = (predDC + 8) >> 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_16x16_PATH_LENGTH; pos++)
		{
			int x = testPntPath16xy[pos][0];
			int y = testPntPath16xy[pos][1];

			/// Accumulate mode distortions here for this sampling point.
				  /// Vertical mode.
			modeDist[MacroBlockH264::Intra_16x16_Vert] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], (int)ref2D[rOffY - 1][rOffX + x]);
			/// DC mode.
			modeDist[MacroBlockH264::Intra_16x16_DC] += DISTORTIONSQRDIFF((int)in2D[iOffY + y][iOffX + x], predDC);
		}//end for pos...

		mode = MacroBlockH264::Intra_16x16_Vert;	///< MacroBlockH264::Intra_16x16_Vert = 0.
		if (modeDist[MacroBlockH264::Intra_16x16_DC] < modeDist[MacroBlockH264::Intra_16x16_Vert])
			mode = MacroBlockH264::Intra_16x16_DC;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Lum value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		pred->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
		pred->Fill(predDC);
		break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
				pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
	}//end Horiz block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra16x16LumPredAndMode.

/** Get Intra Lum prediction.
Apply the prediction mode specified to predict from the ref lum img and write it to the pred
parameter. Used by the decoder.
@param pMb				: Macroblock to predict.
@param ref				: Reference lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@param predMode		: Mode to apply.
@return						: 1 = success, 0 = failure.
*/
int H264v2Codec::GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode)
{
	int i, j;

	short**	ref2D = ref->Get2DSrcPtr();
	int			rOffX = ref->GetOriginX();
	int			rOffY = ref->GetOriginY();
	short**	pred2D = pred->Get2DSrcPtr();
	int			pOffX = pred->GetOriginX();
	int			pOffY = pred->GetOriginY();

	/// Fill the prediction block with the appropriate mode prediction.
	switch (predMode)
	{
	case MacroBlockH264::Intra_16x16_Vert:
	{
		if (pMb->_aboveMb != NULL)	///< Vert prediction only cares about the macroblock above.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY - 1][rOffX + j];
		}//end if aboveMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_16x16_Horiz:
	{
		if (pMb->_leftMb != NULL)	///< Horiz prediction only cares about the macroblock to the left.
		{
			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = ref2D[rOffY + i][rOffX - 1];
		}//end if leftMb...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_16x16_DC:
	{
		bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);
		bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);
		bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);

		int predDC = 0;
		if (aboveAndLeft)
		{
			for (i = 0; i < 16; i++)
				predDC += ((int)ref2D[rOffY - 1][rOffX + i] + (int)ref2D[rOffY + i][rOffX - 1]);
			predDC = (predDC + 16) >> 5;
		}//end if aboveAndLeft...
		else if (leftOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY + i][rOffX - 1];
			predDC = (predDC + 8) >> 4;
		}//end else if leftOnly...
		else if (aboveOnly)
		{
			for (i = 0; i < 16; i++)
				predDC += (int)ref2D[rOffY - 1][rOffX + i];
			predDC = (predDC + 8) >> 4;
		}//end else if aboveOnly...
		else
		{
			predDC = 128;	///< Half the max value.
		}//end else...

		pred->Fill(predDC);
	}//end DC block...
	break;
	case MacroBlockH264::Intra_16x16_Plane:
	{
		bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);

		if (all)	///< All the neighbouring macroblocks must be available for prediction.
		{
			int		H = 0;
			int		V = 0;
			for (i = 0; i < 8; i++)
			{
				H += (i + 1)*((int)ref2D[rOffY - 1][rOffX + 8 + i] - (int)ref2D[rOffY - 1][rOffX + 6 - i]);
				V += (i + 1)*((int)ref2D[rOffY + 8 + i][rOffX - 1] - (int)ref2D[rOffY + 6 - i][rOffX - 1]);
			}//end for i...
			int b = (5 * H + 32) >> 6;
			int c = (5 * V + 32) >> 6;
			int a = ((int)ref2D[rOffY + 15][rOffX - 1] + (int)ref2D[rOffY - 1][rOffX + 15]) << 4;

			for (i = 0; i < 16; i++)
				for (j = 0; j < 16; j++)
					pred2D[pOffY + i][pOffX + j] = H264V2_CLIP255((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
		}//end if all...
		else
		{
			/// Prediction fails.
			pred->Fill(128);	///< Safty net to fill with half max value.
			return(0);
		}//end else...
	}//end Horiz block...
	break;
	}//end switch predMode...

	return(1);
}//end GetIntra16x16LumPred.

/** Get Intra Lum DC prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int dirCnt = 0;
	int predValue = 0;

	short** img = lum->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offLumX;
		offY = pMb->_aboveMb->_offLumY + 15;
		for (i = 0; i < 16; i++)
			predValue += img[offY][offX + i];
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offLumX + 15;
		offY = pMb->_leftMb->_offLumY;
		for (i = 0; i < 16; i++)
			predValue += img[offY + i][offX];
	}//end if _leftMb...

	/// Set the accumulated DC prediction value.
	if (dirCnt == 2)
		predValue = (predValue + 16) >> 5;
	else if (dirCnt == 1)
		predValue = (predValue + 8) >> 4;
	else
		predValue = 128;	///< Half max Lum value.

	pred->Fill(predValue);

}//end GetIntra16x16LumDCPred.

/** Get Intra Lum Plane prediction.
Predict from the input Lum img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use half the
max Lum value (128) as the prediction. The H.264 std does not specify
this last case for Plane pred.
@param pMb				: Macroblock to transform.
@param lum				: Lum img to predict from.
@param pred				: 16x16 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = lum->Get2DSrcPtr();
		int			iOffX = lum->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = lum->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 8; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 8 + i] - (int)img2D[iOffY - 1][iOffX + 6 - i]);
			V += (i + 1)*((int)img2D[iOffY + 8 + i][iOffX - 1] - (int)img2D[iOffY + 6 - i][iOffX - 1]);
		}//end for i...
		int b = (5 * H + 32) >> 6;
		int c = (5 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 15][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 15]) << 4;

		for (i = 0; i < 16; i++)
			for (j = 0; j < 16; j++)
			{
				short x = (short)((a + b*(j - 7) + c*(i - 7) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra16x16LumPlanePred.

/** Get Intra Vertical prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prediction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i;
	MacroBlockH264* amb = pMb->_aboveMb;

	if (amb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last row of the macroblock above.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = amb->_offLumX;
			iOffY = amb->_offLumY + (img->GetHeight() - 1);
		}//end if lumFlag...
		else
		{
			iOffX = amb->_offChrX;
			iOffY = amb->_offChrY + (img->GetHeight() - 1);
		}//end else...
		short* ps = &(img2D[iOffY][iOffX]);
		for (i = 0; i < height; i++)	///< Rows.
			memcpy((void *)(&(pred2D[offY + i][offX])), (const void *)ps, byteLen);
		return(1);
	}//end if amb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Macroblock above does not exist.
}//end GetIntraVertPred.

/** Get Intra Horizontal prediction.
Predict from the input img and write it to the pred parameter. The dimensions
of the pred block define the size of the operation. If there are no valid
neighbours to make the prediction then use half the max value (128) as
the prediction. The H.264 std does not specify this last case for vert pred.
@param pMb				: Macroblock to transform.
@param img				: Img to predict from.
@param pred				: Overlay to write prediction result to.
@param lumFlag		: Is the prodiction for lum?
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag)
{
	int i, j;
	MacroBlockH264* lmb = pMb->_leftMb;

	if (lmb != NULL)
	{
		short**	img2D = img->Get2DSrcPtr();
		short**	pred2D = pred->Get2DSrcPtr();
		int	width = pred->GetWidth();
		int	height = pred->GetHeight();
		int offX = pred->GetOriginX();
		int offY = pred->GetOriginY();
		int byteLen = width * sizeof(short);
		/// The last col of the macroblock to the left.
		int iOffX, iOffY;
		if (lumFlag)
		{
			iOffX = lmb->_offLumX + (img->GetWidth() - 1);
			iOffY = lmb->_offLumY;
		}//end if lumFlag...
		else
		{
			iOffX = lmb->_offChrX + (img->GetWidth() - 1);
			iOffY = lmb->_offChrY;
		}//end else...
		for (i = 0; i < height; i++)	///< Rows.
		{
			short* pd = &(pred2D[offY + i][offX]);
			short  x = img2D[iOffY + i][iOffX];
			for (j = 0; j < width; j++)
				*pd++ = x;
		}//end for i...
		return(1);
	}//end if lmb...

	/// Safety precaution not defined in H.264 standard. If the left macroblock
	/// is not available for prediction then this mode should never be used.
	pred->Fill(128);
	return(0);	///< Left macroblock does not exist.
}//end GetIntraHorizPred.

/** Get Intra Chr prediction.
Select the best prediction mode based on the min distortion with the input img. Predict
from the ref chr img and write it to the pred parameter. Used by the encoder. Return the
intra_8x8 prediction mode.
@param pMb				: Macroblock to predict.
@param cb					: Cb Chr input image.
@param cr					: Cr Chr input image.
@param refCb			: Reference chr Cb img to predict from.
@param refCr			: Reference chr Cr img to predict from.
@param predCb			: 8x8 Cb overlay to write result to.
@param predCr			: 8x8 Cr overlay to write result to.
@return						: Prediction mode.
*/
int H264v2Codec::GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
	OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr,
	OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr)
{
	int i, j;
	int aCb, bCb, cCb, aCr, bCr, cCr;	///< Plane mode intermediates.
	int predCbDC[4] = { 0, 0, 0, 0 };	///< DC mode intermediates.
	int predCrDC[4] = { 0, 0, 0, 0 };
	int modeDist[4] = { 0, 0, 0, 0 }; ///< Accumulator for the distortion tests.

	int mode = MacroBlockH264::Intra_Chr_DC;

	short**	inCb2D = cb->Get2DSrcPtr();
	short**	inCr2D = cr->Get2DSrcPtr();
	int			iOffX = cb->GetOriginX();	///< Assume Cb and Cr have the same offsets.
	int			iOffY = cb->GetOriginY();
	short**	refCb2D = refCb->Get2DSrcPtr();
	short**	refCr2D = refCr->Get2DSrcPtr();
	int			rOffX = refCb->GetOriginX();
	int			rOffY = refCb->GetOriginY();
	short**	predCb2D = predCb->Get2DSrcPtr();
	short**	predCr2D = predCr->Get2DSrcPtr();
	int			pOffX = predCb->GetOriginX();
	int			pOffY = predCr->GetOriginY();

	/// Every mode has intermediate values that the predictions are based on and
	/// these must be prepared first. The values are further dependent on the 
	/// availability of the neighbourhood.
	bool all = (pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL);
	bool aboveOnly = (pMb->_aboveMb != NULL) && (pMb->_leftMb == NULL);	///< Don't care about above left.
	bool leftOnly = (pMb->_aboveMb == NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.
	bool aboveAndLeft = (pMb->_aboveMb != NULL) && (pMb->_leftMb != NULL);	///< Don't care about above left.

	/// The selection process uses a patial sum of the distortion method where a grid of sampling points
	/// is tested with new sets of points at each iteration. If there is no change in the winning mode
	/// after the iteration then that mode is selected.
	int pos = 0;	///< Position in the test sample point array. (Accumulates after each iteration.)
	int noChange = 0;

	if (all)	///< Every mode is a candidate.
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Plane mode preparation --------------------------------------
		int		HCb = 0;
		int		VCb = 0;
		int		HCr = 0;
		int		VCr = 0;
		for (i = 0; i < 4; i++)
		{
			HCb += (i + 1)*((int)refCb2D[rOffY - 1][rOffX + 4 + i] - (int)refCb2D[rOffY - 1][rOffX + 2 - i]);
			VCb += (i + 1)*((int)refCb2D[rOffY + 4 + i][rOffX - 1] - (int)refCb2D[rOffY + 2 - i][rOffX - 1]);
			HCr += (i + 1)*((int)refCr2D[rOffY - 1][rOffX + 4 + i] - (int)refCr2D[rOffY - 1][rOffX + 2 - i]);
			VCr += (i + 1)*((int)refCr2D[rOffY + 4 + i][rOffX - 1] - (int)refCr2D[rOffY + 2 - i][rOffX - 1]);
		}//end for i...
		bCb = (34 * HCb + 32) >> 6;
		cCb = (34 * VCb + 32) >> 6;
		aCb = ((int)refCb2D[rOffY + 7][rOffX - 1] + (int)refCb2D[rOffY - 1][rOffX + 7]) << 4;
		bCr = (34 * HCr + 32) >> 6;
		cCr = (34 * VCr + 32) >> 6;
		aCr = ((int)refCr2D[rOffY + 7][rOffX - 1] + (int)refCr2D[rOffY - 1][rOffX + 7]) << 4;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
			/// Plane mode.
			modeDist[MacroBlockH264::Intra_Chr_Plane] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCb + bCb*(x - 3) + cCb*(y - 3) + 16) >> 5))) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], H264V2_CLIP255((aCr + bCr*(x - 3) + cCr*(y - 3) + 16) >> 5))));
		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 4; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end if all...
	else if (aboveAndLeft)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += ((int)refCb2D[rOffY - 1][rOffX + i] + (int)refCb2D[rOffY + i][rOffX - 1]);
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];
			predCbDC[3] += ((int)refCb2D[rOffY - 1][rOffX + 4 + i] + (int)refCb2D[rOffY + 4 + i][rOffX - 1]);

			predCrDC[0] += ((int)refCr2D[rOffY - 1][rOffX + i] + (int)refCr2D[rOffY + i][rOffX - 1]);
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
			predCrDC[3] += ((int)refCr2D[rOffY - 1][rOffX + 4 + i] + (int)refCr2D[rOffY + 4 + i][rOffX - 1]);
		}//end for i...

	/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 4) >> 3;
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = (predCbDC[3] + 4) >> 3;

		predCrDC[0] = (predCrDC[0] + 4) >> 3;
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = (predCrDC[3] + 4) >> 3;

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int quadrant = 0;
			if ((y < 4) && (x > 3))
				quadrant = 1;
			else if (y > 3)
			{
				if (x < 4)
					quadrant = 2;
				else
					quadrant = 3;
			}//end else if y...
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[quadrant])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[quadrant])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		for (i = MacroBlockH264::Intra_Chr_Horiz; i < 3; i++)	///< Total of 4 modes.
		{
			if (modeDist[i] < modeDist[mode])
				mode = i;
		}//end for i...

	}//end else if aboveAndLeft...
	else if (leftOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY + i][rOffX - 1];
			predCbDC[2] += (int)refCb2D[rOffY + 4 + i][rOffX - 1];

			predCrDC[0] += (int)refCr2D[rOffY + i][rOffX - 1];
			predCrDC[2] += (int)refCr2D[rOffY + 4 + i][rOffX - 1];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[1] = predCbDC[0];
		predCbDC[2] = (predCbDC[2] + 2) >> 2;
		predCbDC[3] = predCbDC[2];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[1] = predCrDC[0];
		predCrDC[2] = (predCrDC[2] + 2) >> 2;
		predCrDC[3] = predCrDC[2];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (y > 3)
				partition = 2;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Horiz mode.
			modeDist[MacroBlockH264::Intra_Chr_Horiz] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY + y][rOffX - 1])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY + y][rOffX - 1])));
		}//end for pos...

		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Horiz] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Horiz;

	}//end else if leftOnly...
	else if (aboveOnly)
	{
		///------------------- DC mode preparation -----------------------------------------
		for (i = 0; i < 4; i++)	///< Accumulate sums.
		{
			predCbDC[0] += (int)refCb2D[rOffY - 1][rOffX + i];
			predCbDC[1] += (int)refCb2D[rOffY - 1][rOffX + 4 + i];

			predCrDC[0] += (int)refCr2D[rOffY - 1][rOffX + i];
			predCrDC[1] += (int)refCr2D[rOffY - 1][rOffX + 4 + i];
		}//end for i...
		/// Calculate average values.
		predCbDC[0] = (predCbDC[0] + 2) >> 2;
		predCbDC[2] = predCbDC[0];
		predCbDC[1] = (predCbDC[1] + 2) >> 2;
		predCbDC[3] = predCbDC[1];

		predCrDC[0] = (predCrDC[0] + 2) >> 2;
		predCrDC[2] = predCrDC[0];
		predCrDC[1] = (predCrDC[1] + 2) >> 2;
		predCrDC[3] = predCrDC[1];

		///------------------- Test for min ------------------------------------------------
		for (pos = 0; pos < H264V2_8x8_PATH_LENGTH; pos++)
		{
			int x = testPntPath8xy[pos][0];
			int y = testPntPath8xy[pos][1];

			/// Accumulate mode distortions here for these 4 points.
				  /// DC mode.
			int partition = 0;
			if (x > 3)
				partition = 1;
			modeDist[MacroBlockH264::Intra_Chr_DC] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], predCbDC[partition])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], predCrDC[partition])));
			/// Vertical mode.
			modeDist[MacroBlockH264::Intra_Chr_Vert] += ((DISTORTIONSQRDIFF((int)inCb2D[iOffY + y][iOffX + x], (int)refCb2D[rOffY - 1][rOffX + x])) +
				(DISTORTIONSQRDIFF((int)inCr2D[iOffY + y][iOffX + x], (int)refCr2D[rOffY - 1][rOffX + x])));

		}//end for pos...
		mode = MacroBlockH264::Intra_Chr_DC;	///< MacroBlockH264::Intra_Chr_DC = 0.
		if (modeDist[MacroBlockH264::Intra_Chr_Vert] < modeDist[MacroBlockH264::Intra_Chr_DC])
			mode = MacroBlockH264::Intra_Chr_Vert;

	}//end else if aboveOnly...
	else
	{
		/// Use the DC default mode when there are no valid neighbours and use half the 
		/// max Chr value (128) as the prediction. This is typically the top left corner
		/// of the slice.
		predCb->Fill(128);
		predCr->Fill(128);
		return(mode);	///< Early exit.
	}//end else...

	/// Fill the prediction block with the lowest distortion mode prediction.
	switch (mode)
	{
	case MacroBlockH264::Intra_Chr_DC:
	{
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = predCbDC[0];
				predCb2D[pOffY + i][pOffX + 4 + j] = predCbDC[1];
				predCb2D[pOffY + 4 + i][pOffX + j] = predCbDC[2];
				predCb2D[pOffY + 4 + i][pOffX + 4 + j] = predCbDC[3];

				predCr2D[pOffY + i][pOffX + j] = predCrDC[0];
				predCr2D[pOffY + i][pOffX + 4 + j] = predCrDC[1];
				predCr2D[pOffY + 4 + i][pOffX + j] = predCrDC[2];
				predCr2D[pOffY + 4 + i][pOffX + 4 + j] = predCrDC[3];
			}//end for i & j...
	}//end DC block...
	break;
	case MacroBlockH264::Intra_Chr_Horiz:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY + i][rOffX - 1];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY + i][rOffX - 1];
			}//end i & j...
	}//end Horiz block...
	break;
	case MacroBlockH264::Intra_Chr_Vert:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = refCb2D[rOffY - 1][rOffX + j];
				predCr2D[pOffY + i][pOffX + j] = refCr2D[rOffY - 1][rOffX + j];
			}//end for i & j...
	}//end Vert block...
	break;
	case MacroBlockH264::Intra_Chr_Plane:
	{
		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				predCb2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCb + bCb*(j - 3) + cCb*(i - 3) + 16) >> 5);
				predCr2D[pOffY + i][pOffX + j] = H264V2_CLIP255((aCr + bCr*(j - 3) + cCr*(i - 3) + 16) >> 5);
			}//end for i & j...
	}//end Plane block...
	break;
	}//end switch mode...

	return(mode);
}//end GetIntra8x8ChrPredAndMode.

/** Get Intra Chr DC prediction.
Predict from the parameter Chr img and write it to the pred parameter. If
there are no valid neighbours to make the prediction then use the
mid chr value (128) as the prediction. The H.264 std does not specify
this last case for DC pred.
@param pMb				: Macroblock to transform.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: none
*/
void H264v2Codec::GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int offX, offY, i;
	int predValue[4];
	int dirCnt = 0;
	int sum[4] = { 0, 0, 0, 0 };

	short** img = chr->Get2DSrcPtr();

	if (pMb->_aboveMb != NULL)
	{
		dirCnt++;
		/// The last row of the macroblock above.
		offX = pMb->_aboveMb->_offChrX;
		offY = pMb->_aboveMb->_offChrY + 7;
		for (i = 0; i < 4; i++)
		{
			sum[0] += img[offY][offX + i];
			sum[1] += img[offY][offX + 4 + i];
		}//end for i...
	}//end if _aboveMb...

	if (pMb->_leftMb != NULL)
	{
		dirCnt++;
		/// The last col of the macroblock to the left.
		offX = pMb->_leftMb->_offChrX + 7;
		offY = pMb->_leftMb->_offChrY;
		for (i = 0; i < 4; i++)
		{
			sum[2] += img[offY + i][offX];
			sum[3] += img[offY + 4 + i][offX];
		}//end for i...
	}//end if _leftMb...

	/// Set the accumulated DC prediction values.
	if (dirCnt == 2)
	{
		predValue[0] = (sum[0] + sum[2] + 4) >> 3;
		predValue[1] = (sum[1] + 2) >> 2;
		predValue[2] = (sum[3] + 2) >> 2;
		predValue[3] = (sum[1] + sum[3] + 4) >> 3;
	}//end if dirCnt...
	else if (dirCnt == 1)
	{
		if (pMb->_leftMb == NULL)
		{
			predValue[0] = (sum[0] + 2) >> 2;
			predValue[1] = (sum[1] + 2) >> 2;
			predValue[2] = (sum[0] + 2) >> 2;
			predValue[3] = (sum[1] + 2) >> 2;
		}//end if !leftMb...
		else
		{
			predValue[0] = (sum[2] + 2) >> 2;
			predValue[1] = (sum[2] + 2) >> 2;
			predValue[2] = (sum[3] + 2) >> 2;
			predValue[3] = (sum[3] + 2) >> 2;
		}//end else...
	}//end else if dirCnt...
	else
	{
		/// Mid Chr value.
		predValue[0] = 128;
		predValue[1] = 128;
		predValue[2] = 128;
		predValue[3] = 128;
	}//end else...

	int xBase = pred->GetOriginX();
	int yBase = pred->GetOriginY();
	pred->SetOverlayDim(4, 4);
	for (int y = 0, i = 0; y < 2; y++)
		for (int x = 0; x < 2; x++, i++)
		{
			pred->SetOrigin(xBase + x * 4, yBase + y * 4);
			pred->Fill(predValue[i]);
		}//end for y & x...

	/// Put the block back into shape.
	pred->SetOverlayDim(8, 8);
	pred->SetOrigin(xBase, yBase);

}//end GetIntra8x8ChrDCPred.

/** Get Intra Chr Plane prediction.
Predict from the parameter Chr img and write it to the pred parameter. This
implementation if for YCbCr 4:2:0 chroma_format_idc = 1 only. If there are
no valid neighbours to make the prediction then use the mid chr value (128)
as the prediction. The H.264 std does not specify this last case for DC pred.
@param pMb				: Macroblock to predict.
@param chr				: Chr img to predict from.
@param pred				: 8x8 overlay to write result to.
@return						: 1 = pred was made, 0 = no macroblocks available for pred.
*/
int H264v2Codec::GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred)
{
	int i, j;

	if ((pMb->_aboveMb != NULL) && (pMb->_aboveLeftMb != NULL) && (pMb->_leftMb != NULL))
	{
		short**	img2D = chr->Get2DSrcPtr();
		int			iOffX = chr->GetOriginX();	///< Top left of img2D pMb location.
		int			iOffY = chr->GetOriginY();
		short**	pred2D = pred->Get2DSrcPtr();
		int			pOffX = pred->GetOriginX();
		int			pOffY = pred->GetOriginY();

		int		H = 0;
		int		V = 0;
		for (i = 0; i < 4; i++)
		{
			H += (i + 1)*((int)img2D[iOffY - 1][iOffX + 4 + i] - (int)img2D[iOffY - 1][iOffX + 2 - i]);
			V += (i + 1)*((int)img2D[iOffY + 4 + i][iOffX - 1] - (int)img2D[iOffY + 2 - i][iOffX - 1]);
		}//end for i...
		int b = (34 * H + 32) >> 6;
		int c = (34 * V + 32) >> 6;
		int a = ((int)img2D[iOffY + 7][iOffX - 1] + (int)img2D[iOffY - 1][iOffX + 7]) << 4;

		for (i = 0; i < 8; i++)
			for (j = 0; j < 8; j++)
			{
				short x = (short)((a + b*(j - 3) + c*(i - 3) + 16) >> 5);
				pred2D[pOffY + i][pOffX + j] = (short)(H264V2_CLIP255(x));
			}//end for i & j...

		return(1);	///< Successful prediction.
	}//end if _aboveMb...

	/// Safety precaution not defined in H.264 standard. If the macroblock above, 
	/// above left and left are not available for prediction then this mode should 
	/// never be used.
	pred->Fill(128);
	return(0);	///< Prediction macroblocks do not exist.
}//end GetIntra8x8ChrPlanePred.

/*
-----------------------------------------------------------------------
  Private nested classes.
-----------------------------------------------------------------------
*/
/** Encode the image data for Intra IDR pictures.
Process all slices and their macroblocks in order. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
#ifdef H264V2_DUMP_MB_RD_DATA

		if ((mb > 66) && (_codec->_mbRDTablePos < 65)) ///< Collect data for 64 mbs starting in the 3rd mb row of the image.
		{
			/// Write the mb number in row 0.
			_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, 0, mb);

			int qp;
			for (qp = 1; qp < _codec->_mbRDTableLen; qp++)
			{
				_codec->_pMb[mb]._mbQP = qp;
				_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 2);  ///< D only.

				_codec->_mbRDTable.WriteItem(_codec->_mbRDTablePos, qp, _codec->_pMb[mb]._distortion[qp]);
			}//end for qp...

			_codec->_mbRDTablePos++;  ///< Represents columns. 
		}//end if mb...

#endif /// H264V2_DUMP_MB_RD_DATA

		_codec->_pMb[mb]._mbQP = _codec->_slice._qp;
		_codec->ProcessIntraMbImplStd(&(_codec->_pMb[mb]), 0);
	}//end for mb...

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplStdVer1::Encode.

/** Decode of the Intra macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		/// --------------------- Inverse Transform & Quantisation --------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			_codec->InverseTransAndQuantIntra16x16MBlk(pMb, 0);

		/// --------------------- Image Prediction and Storing -------------------------------------
		/// From the prediction mode settings, make the appropriate prediction macroblock and then
		/// add the inverse transformed and quantised values to it. Fill the image (difference) colour 
		/// components from all the non-DC 4x4 blks (i.e. Not blks = -1, 17, 18) of the macroblock blocks.

		/// Store blocks into ref img.
		MacroBlockH264::StoreBlks(pMb, _codec->_RefLum, lOffX, lOffY, _codec->_RefCb, _codec->_RefCr, cOffX, cOffY, 0);

		/// Predict the output from the previously decoded neighbour ref macroblocks.
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.

		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefLum, _codec->_16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			_codec->GetIntra16x16LumDCPred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			_codec->GetIntra16x16LumPlanePred(pMb, _codec->_RefLum, _codec->_16x16);
			break;
		}//end switch _intra16x16PredMode...

		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);

		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrDCPred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			_codec->GetIntraHorizPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraHorizPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			_codec->GetIntraVertPred(pMb, _codec->_RefCb, _codec->_8x8_0, 0);
			_codec->GetIntraVertPred(pMb, _codec->_RefCr, _codec->_8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCb, _codec->_8x8_0);
			_codec->GetIntra8x8ChrPlanePred(pMb, _codec->_RefCr, _codec->_8x8_1);
			break;
		}//end switch _intraChrPredMode...

		/// --------------------- Add the prediction -----------------------------------------------
		/// Lum.
		_codec->_RefLum->SetOverlayDim(16, 16);
		_codec->_RefLum->SetOrigin(lOffX, lOffY);           ///< Align the Ref Lum img block with this macroblock.
		_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add pred to ref Lum and leave result in ref img.
		/// Cb.
		_codec->_RefCb->SetOverlayDim(8, 8);
		_codec->_RefCb->SetOrigin(cOffX, cOffY);
		_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
		/// Cr.
		_codec->_RefCr->SetOverlayDim(8, 8);
		_codec->_RefCr->SetOrigin(cOffX, cOffY);
		_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

	}//end for mb...

	return(1);
}//end IntraImgPlaneDecoderImplStdVer1::Decode.

/** Encode the image data for Intra pictures with adaptive PQ (minmax).
The encoder seeks to find the optimal quant value for each macroblock using a minmax algorithm with
the constraint of a max number of bits specified in the method parameter list by allowedBits.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: 1/0 = do/do not update ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int len = _codec->_mbLength;
	int mb;
	/// Mark the macroblock from where min bit rate macroblocks must be encoded if the slice is to be truncated.
	int minMBIndex = len;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPIntra;

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Initialisation step: 
	///		lower(D,R) : QP = H264V2_MAX_QP.
	///		upper(D,R) : QP = 1.
	/// Note that the D values represent the worst (max) distortion of only one macroblock in the entire
	/// frame but the R values represent the accumulated (total) rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int mbDmax = 0;
	int	invalidated = 0;
	int	iterations = 0;
	/*
	  /// --------------------- I-Frame Measurement Collection -----------------------------------------------------
	  /// --------------------------------------------------------------------------------------------------
	*/
	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest (max) distortion of all macroblocks.
		Rl += _codec->ProcessIntraMbImplStd(pMb, 1);
		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the macroblock with the peak distortion.
		}//end if _distortion...

	}//end for mb...

  /// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer and assume half required after exiting.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_intraIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (start - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt else do damage control.
	int bitCost = Rl;
	int oldBitCount = Rl;
	if (Rl <= allowedBits)
	{
		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	/// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int goingDown = 1;
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			int model = 0;
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
			{
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);
				model = 1;
			}//end if linear...

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
			{
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.
				model = 2;
			}//end if bisection...

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;

			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// If the previous neighbourhood has not changed and QP is the same as the last encoding of this blk
				/// then it does not have to be re-encoded assuming distortion < Dmax.
				if ((mb >= firstMbChange) || (_pQ[mb] != pMb->_mbEncQP) || (pMb->_distortion[_pQ[mb]] > Dmax))
				{
					/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					pMb->_mbQP = _pQ[mb];
					if (_pQ[mb] > 24)  ///< Assume that below QP = 24 the prediction mode will be the same.
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 0, Dmax, qEnd);
					else
						R += _codec->ProcessIntraMbImplStd(pMb, 1, 1, Dmax, qEnd);
					_pQ[mb] = pMb->_mbQP;

					if (mb < firstMbChange)
						firstMbChange = mb;
				}//end if mb...
				else
					R += pMb->_rate[_pQ[mb]];

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 
			}//end for mb...

	//			for(mb = 0; mb < len; mb++)
	//			{
	//				MacroBlockH264* pMb = &(_codec->_pMb[mb]);
	//				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, 1);
	//				R += pMb->_rate[_pQ[mb]];
	//      }//end for mb...

				/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		/// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _pQ[mb];
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax path Allowed=%d Cost=%d Invalid=%d", allowedBits, R, invalidated);
		//sprintf(_codec->_errorInfo, "I-frame: Normal minmax");
		bitCost = R;

	}//end if Rl...
	else ///< For QP = H264V2_MAX_QP the max allowed bits was exceeded and damage control is required.
	{
		///======================================================================================

		/// Sub-optimal Steepest Ascent Algorithm
		bitCost = DamageControl(allowedBits, bitCost);

		if (bitCost >= allowedBits) ///< All failed.
		{
			minMBIndex = _codec->_lumWidth / 16; ///< Hope for the best.
			invalidated = 1;
			for (int mb = 0; mb < len; mb++)
				_codec->_pMb[mb]._mbQP = _codec->_pMb[mb]._mbEncQP;
		}//end if bitCost...

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "I-frame: Damage control path Allowed=%d Cost=%d Iter=%d ListLen=%d ReorderCnt=%d", allowedBits, bitCost, iterations, listLen, cnt);
		//sprintf(_codec->_errorInfo, "I-frame: Damage control");

	}//end else...

	/// Apply the selected quant with the full feedback loop to all macroblocks.
	if (invalidated)
	{
		//  	int bitCount = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// Encode the macroblocks until min null macroblocks.
			if (mb < minMBIndex)
				_codec->ProcessIntraMbImplStd(pMb, 0);
			//  			bitCount += _codec->ProcessIntraMbImplStd(pMb, 1);
			else
				_codec->ProcessIntraMbImplStdMin(pMb);
			//  			bitCount += _codec->ProcessIntraMbImplStdMin(pMb);

		}//end for mb...

  //    bitCost = bitCount;

	}//end if invalidated...

	*bitsUsed = 0;
	//  *bitsUsed = bitCost;
	return(1);
}//end IntraImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm
At max QP for all Mbs the rate limit is exceeded and an alternative quantisation
approach is taken to use the available bits as best as possible. This implementation
zeros more and more of the DCT coeffs until it fits using a sub-optimal Steepest
Ascent Algorithm.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used up to this point.
@return             : The actual bits consumed.
*/
int H264v2Codec::IntraImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	int i, mb;
	int bitCost = currBitCost;
	int iterations = 0;
	int cnt;

	/// Initialise the ordered mb list.
	int len = _codec->_mbLength;
	int listLen = len;
	for (mb = 0; mb < len; mb++)
		_pMbList[mb] = mb;

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the mbs in increasing distortion.

			/// Exclude completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (_codec->_pMb[mb]._mbEncQP < H264V2_I_MAX_EXT_QP)
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_I_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_I_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 66; break;
					case 66: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 77; break;
					case 77: pMb->_mbQP = 81; break;
					case 81: pMb->_mbQP = 84; break;
					case 84: pMb->_mbQP = 85; break;
					case 85: pMb->_mbQP = 86; break;
					default: pMb->_mbQP = 86; break;
					}///end switch _mbEncQP...

					_codec->ProcessIntraMbImplStd(pMb, 2, 1); ///< Distortion only and without pred mode selection.

				}//end while _distortion[]...

				/// Add back new bits.
				pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
				predR += pMb->_rate[pMb->_mbEncQP];

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessIntraMbImplStd(pMb, 1, 1);
		}//end for mb...

		iterations++;
	}//end while bitCost...

	return(bitCost);
}//end IntraImgPlaneEncoderImplMinMax::DamageControl.

/** Encode the image data for Intra IDR pictures with a mb Dmax limit.
Process all slices and their macroblocks in order. The QP value is decremented
until the mb Dmax is less than the codec _dMax parameter. The reference is always
written into for this implementation regardless of the state of the writeRef
parameter. It is required for for later macroblock prediction. The macroblock
objs are prepared for coding onto the bit stream. The inclusion of the allowed
bits param provides for scope to use bit allocation procedures. Ver. 1 limits
the encoding to a single slice with no partitioning.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding (return value).
@param writeRef			: Ignored.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::IntraImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the Dxax search is limited to.
	int qEnd = _codec->_minQPIntra;
	int coeffBits = 0;

	if (_codec->_modeOfOperation == H264V2_MB_QP_DMAX_ADAPTIVE)
		if ((_codec->_iPictureDMaxMultiplier != 0) || (_codec->_iPictureDMaxMultiplier != 0))
			/// Modify the Dmax value by the I-Picture multiplier and fraction.
			dmax = (dmax * _codec->_iPictureDMaxMultiplier) + ((dmax * _codec->_iPictureDMaxFraction) / 10);

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_16x16->SetOrigin(0, 0);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_0->SetOrigin(0, 0);
	_codec->_8x8_1->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOrigin(0, 0);

	/// All integer transforms are Intra in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.
	_codec->_pFDC4x4T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);
	_codec->_pFDC2x2T->SetParameter(IForwardTransform::INTRA_FLAG_ID, 1);

	/// Whip through each macroblock in the slice and encode. The stream writing of
	/// the macroblock is seperate to allow further decision making later.
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// The 1st macroblock has a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		/// Descend the QP value until the mb distortion is less than dmax.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessIntraMbImplStd(pMb, 1, 0, dmax, qEnd);
		else
			_codec->ProcessIntraMbImplStd(pMb, 2, 0, dmax, qEnd);
	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end IntraImgPlaneEncoderImplDMax::Encode.

/** Get distortion from an r vs d power model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistPowerModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if ((dl != du) && (rl != ru))
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a power function.
		double beta = -(log((double)rl / (double)ru)) / (log((double)dl / (double)du));
		double alpha = (double)rl / (pow((double)dl, -beta));
		/// Use the power function to predict where r will be. r = alpha.d^(-beta)
		d = (int)exp(-log((double)r / alpha) / beta);
	}//end if dl...

	return(d);
}//end FitDistPowerModel.

/** Get distortion from an r vs d linear model.
@return	:	Distortion predicted
*/
int H264v2Codec::FitDistLinearModel(int rl, int dl, int ru, int du, int r)
{
	int d = dl;
	if (rl != ru)
	{
		/// Curve fit the points (rl,dl) and (ru,du) to a linear function.
		d = (int)((double)((r - rl)*(dl - du)) / (double)(rl - ru)) + dl;
	}//end if dl...

	return(d);
}//end FitDistLinearModel.

/** Get the next quant QP value that has a distortion less than Dmax.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra)
{
	/// 1st iteration required to ensure sync with macroblock dependencies if
	/// it was invalidated or changed since last encoding.
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);

		di = mb._distortion[i];
	}//end if mbIndex...

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if (i < H264V2_MAX_QP)
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
//			int previ = i;
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				//				previ = i;
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmax.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// The delta QP for a mb is constrained to {-26...25}. Therefore if
	/// the current QP value results in a dQP > 25 or < -26 then it must 
	/// be reprocessed before continuing regardless of the Dmax value. The
	/// i not equal to atQ signals that delta QP was out of range.
	int prevQP = GetPrevMbQP(&mb);
	int minQP = prevQP - 26;
	if (minQP < lowestQ) minQP = lowestQ;
	int maxQP = prevQP + 25;
	if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
	if (i < minQP) i = minQP;
	else if (i > maxQP) i = maxQP;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb or delta QP was out of range then
  /// its dependencies have been altered and it must be re-encoded.
	if ((mbIndex >= lclChangeMb) || (i != atQ))
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
			else
				ProcessInterMbImplStd(&mb, 0, 2);         ///< Distortion only.
		}//end if !intra...
		else
			ProcessIntraMbImplStd(&mb, 2, 0); ///< Distortion only.

		di = mb._distortion[i];
	}//end if mbIndex...

	/// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 2);
			else
				ProcessIntraMbImplStd(&mb, 2, 1); ///< Distortion only without pred mode selection.

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

  /// Set the new mb rate at this QP value.
	if (!intra)
	{
		int rate = 0;
		if (!mb._skip)
			rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
		mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.
	}//end if !intra...
	else
		mb._rate[mb._mbEncQP] = MacroBlockLayerBitCounter(&mb);

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer2.

/** Get the next quant value that has a distortion less than Dmax with decrement only.
This method includes extended QP values = {52..71}.
@param mb						: Macroblock to operate on.
@param atQ					: Current q for this macroblk.
@param Dmax					: Max value to get below.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQ			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra)
{
	int i = atQ;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded.
	if (mbIndex >= lclChangeMb)
	{
		mb._mbQP = i;
		if (!intra)
		{
			/// For P mbs, if the previous encoding QP was the same then only the rate of the mb
			/// will change. This rate change is due to a change in the number of coeffs of neighbouring
			/// mbs and their changed QP values.
			if (mb._mbEncQP == i)
			{
				if (mb._mbQP > H264V2_MAX_QP)              ///< For extended QP range, temporarily reset for processes below.
					mb._mbQP = H264V2_MAX_QP;

				int rate = 0;
				mb._mb_qp_delta = GetDeltaQP(&mb);        ///< Process new delta QP.
				if (!mb._skip)
					rate = MacroBlockLayerBitCounter(&mb);  ///< Process mb for new neighbour coeffs values.
				mb._rate[mb._mbEncQP] = rate;             ///< Update this new rate.

				mb._mbQP = i;                             ///< Put it back.
			}//end if _mbEncQP...
			else
			{
				ProcessInterMbImplStd(&mb, 0, 1);
			}//end else...

		}//end if !intra...
		else
		{
			ProcessIntraMbImplStd(&mb, 1);
		}//end else...

		di = mb._distortion[i];
	}//end if mbIndex...

  /// The delta QP for a mb is constrained to {-26...25}. Therefore if
  /// the current QP value results in a dQP > 25 or < -26 then it must 
  /// be reprocessed before continuing regardless of the Dmax value.
	int minQP = lowestQ;
	if (i <= H264V2_MAX_QP) ///< Only for the non-extended QP range.
	{
		int prevQP = GetPrevMbQP(&mb);
		minQP = prevQP - 26;
		if (minQP < lowestQ) minQP = lowestQ;
		int maxQP = prevQP + 25;
		if (maxQP > H264V2_MAX_QP) maxQP = H264V2_MAX_QP;
		if ((i < minQP) || (i > maxQP))
		{
			if (i < minQP) i = minQP;
			else i = maxQP;
			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];
		}//end if i...
	}//end if i...

	  /// Check if it is necessary to look further.
	if ((i > minQP) && (di > Dmax))
	{
		if (mbIndex < lclChangeMb)
			lclChangeMb = mbIndex;

		/// Iterate QP down from i. If i drops to minQP without di <= Dmax
		/// then leave, as it is the best that can be done.
		while ((i > minQP) && (di > Dmax))
		{
			i -= MbStepSize[i];
			if (i < minQP) i = minQP;

			mb._mbQP = i;
			if (!intra)
				ProcessInterMbImplStd(&mb, 0, 1);
			else
				ProcessIntraMbImplStd(&mb, 1);

			di = mb._distortion[i];

		}//end while i...
	}//end if i...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMacroblkQuantBelowDmaxVer3.

/** Get the next quant QP value that has a distortion less than Dmax with approximations.
@param mb						: Macroblock to operate on.
@param atQP					: Current QP for this macroblk.
@param Dmax					: Max value to get below.
@param epsilon			: The Dmax approximation only has to be within epsilon of Dmax.
@param decQP				: Decrement=1/increment=0 QP from atQ for this macroblock.
@param changeMb			: Macroblock index from where the last change was made.
@param lowestQP			: Lowest allowed quant.
@param intra				: Is macroblock Intra.
@return							: QP value that has dist < Dmax for this macroblock.
*/
int H264v2Codec::GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra)
{
	int i = atQP;
	int	di = mb._distortion[i];
	int mbIndex = mb._mbIndex;
	int lclChangeMb = *changeMb;

	/// Macroblocks are dependent on (predicted from) previous macroblocks in the slice. If
	/// this mb is located after the previously changed mb then its dependencies have been
	/// altered and it must be re-encoded. However, as it will be changed anyway, either up
	/// or down, a short cut approximation is to assume that the previous encoding at the
	/// current QP is approximately correct and the descent/ascent proceeds with these values.
	/// But the mb must be processed at least once before exiting to be valid.
	int atLeastOnce = 0;

	/// If an increasing QP is requested but di > Dmax then a decrease
	/// in mb QP is actually what is required.
	if (!decQP && (di > Dmax))
		decQP = 1;

	if (decQP)	///< Decreasing QP until di < Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i > lowestQP) && (di > Dmax))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP down from i. If i drops to lowestQ without di <= Dmax
			/// then leave as it is the best that can be done.
			while ((i > lowestQP) && (di > Dmax))
			{
				i -= MbStepSize[i];
				if (i < lowestQP)
					i = lowestQP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

		}//end if i...
	}//end if decQP...
	else		///< Increasing QP until di > Dmax and then decrease back to below Dmax.
	{
		/// Check if it is necessary to look further.
		if ((i < H264V2_MAX_QP) && ((Dmax - di) > epsilon))
		{
			if (mbIndex < lclChangeMb)
				lclChangeMb = mbIndex;

			atLeastOnce = 1;	///< Signal that the mb is encoded.

			/// Iterate QP up from i until di > Dmax or i = H264V2_MAX_QP (51).
			while ((i < H264V2_MAX_QP) && (di <= Dmax))
			{
				i += MbStepSize[i];
				if (i > H264V2_MAX_QP)
					i = H264V2_MAX_QP;

				mb._mbQP = i;
				if (!intra)
					;
				else
					ProcessIntraMbImplStd(&mb, 1);
				di = mb._distortion[i];
			}//end while i...

			/// Compensate only if a solution was found otherwise QP = H264V2_MAX_QP is the
			/// best that can be done. It is expected to step back only once but if the step
			/// up process above was not implemented because di > Dmax then iterating down
			/// several times may be required.
			if (di > Dmax)
			{
				/// Iterate down from i. If i drops to lowestQ without di <= Dmax
				/// then leave as it is the best that can be done.
				while ((i > lowestQP) && (di > Dmax))
				{
					i -= MbStepSize[i];
					if (i < lowestQP)
						i = lowestQP;

					mb._mbQP = i;
					if (!intra)
						;
					else
						ProcessIntraMbImplStd(&mb, 1);
					di = mb._distortion[i];
				}//end while i...

			}//end if di...

		}//end if i...

	}//end else...

	/// Re-sync the mb if it was not already processed.
	if ((mbIndex >= lclChangeMb) && (!atLeastOnce))
	{
		mb._mbQP = i;
		if (!intra)
			;
		else
			ProcessIntraMbImplStd(&mb, 1);
	}//end if mbIndex...

	/// Return QP value where dist just less than Dmax for this macroblock.
	*changeMb = lclChangeMb;
	return(i);
}//end GetMbQPBelowDmaxApprox.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		: Macroblock to operate on.
@param withDR	: With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@return				: Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode and get the prediction. Pred stored in _16x16.
	pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
	if (withDR)
		pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock.
Code factoring usage. Includes reading the input image, IT, quantisation,
vlc encoding and determining coding patterns, type, etc. Return the
bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP; ///< This method may alter the mb QP therefore keep an orignal copy.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.
	/// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation with Inverse -----------------------------------
	int mbDistortion = 0;
	if (pMb->_mbEncQP <= H264V2_MAX_QP)
	{
		/// ------------------ Calc distortion from the feedback loop --------------------------------
		/// Implement the forward and feedback loop into the ref image. The forward block coeffs are 
	  /// still required for the context-aware vlc coding and therefore the temporary working blocks 
	  /// are used for this feedback loop. The distortion returned includes ROI modification.
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			mbDistortion = TransAndQuantIntra16x16MBlkWithInv(pMb, withDR);
	}//end if_mbEncQP...
	else ///< if( pMb->_mbEncQP > H264V2_MAX_QP)
	{
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			TransAndQuantIntra16x16MBlk(pMb);

		/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------
		CoeffZeroingQuantisation(pMb);

		///---------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
			InverseTransAndQuantIntra16x16MBlk(pMb, 1);

		///---------------------- Lum Distortion -------------------------------------------------
		if (withDR)
		{
			/// Ref holds the pre-quant diff with the pred and the temp blks hold the post-quant diff
			/// to compare with.
			_RefLum->SetOverlayDim(4, 4);
			int i, j;
			for (i = 0; i < 4; i++)
				for (j = 0; j < 4; j++)
				{
					_RefLum->SetOrigin(lOffX + 4 * j, lOffY + 4 * i); ///< Align with blk.
#ifdef USE_ABSOLUTE_DIFFERENCE
					mbDistortion += _RefLum->Tad4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#else
					mbDistortion += _RefLum->Tsd4x4(*(pMb->_lumBlkTmp[i][j].GetBlkOverlay()));
#endif
				}//end for i & j...

      /// Region of interest modification.
      mbDistortion = ROIDistortion(pMb->_mbIndex, mbDistortion);
		}//end if withDR...

	}//end else...

	/// --------------------- Set distortion -------------------------------------------------
  if (withDR)
    pMb->_distortion[pMb->_mbEncQP] = mbDistortion;

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
		pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** The forward and inverse loop of a Std Intra macroblock with a max distortion criterion.
Code factoring usage. Includes reading the input image, IT, quantisation, vlc encoding and
determining coding patterns, type, etc. _mbQP is decremented until the lum distortion is
below Dmax. If distortion for the given _mbQP is below Dmax then the mb is processed only
once, there is no ascent search. _mbQP must be less than or equal to H264V2_MAX_QP, coeff
zeroing is not implemented in this overload. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined as the starting QP value before this method is called.

  /// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		///< Align the Lum img block with this macroblock.

  /// Frame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _Lum->Read(c, r);
					if (c)
						prev = _Lum->Read(c - 1, r); ///< Left.
					else
						prev = _Lum->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// Select the best mode or use the previous mode and get the prediction. Pred stored in _16x16.
	if (usePrevPred)
	{
		switch (pMb->_intra16x16PredMode)
		{
		case MacroBlockH264::Intra_16x16_Vert:
			GetIntraVertPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_Horiz:
			GetIntraHorizPred(pMb, _RefLum, _16x16, 1);
			break;
		case MacroBlockH264::Intra_16x16_DC:
			GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);
			break;
		case MacroBlockH264::Intra_16x16_Plane:
			GetIntra16x16LumPlanePred(pMb, _RefLum, _16x16);
			break;
		}//end switch _intra16x16PredMode...
	}//end if usePrevPred...
	else
		pMb->_intra16x16PredMode = GetIntra16x16LumPredAndMode(pMb, _Lum, _RefLum, _16x16);

	_Lum->Read(*(_RefLum));						///< Read from input Lum into ref Lum.
	_RefLum->Sub16x16(*(_16x16));			///< Subtract pred from ref Lum and leave result in ref img.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	if (usePrevPred)
	{
		switch (pMb->_intraChrPredMode)
		{
		case MacroBlockH264::Intra_Chr_DC:
			GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);
			break;
		case MacroBlockH264::Intra_Chr_Horiz:
			GetIntraHorizPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraHorizPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Vert:
			GetIntraVertPred(pMb, _RefCb, _8x8_0, 0);
			GetIntraVertPred(pMb, _RefCr, _8x8_1, 0);
			break;
		case MacroBlockH264::Intra_Chr_Plane:
			GetIntra8x8ChrPlanePred(pMb, _RefCb, _8x8_0);
			GetIntra8x8ChrPlanePred(pMb, _RefCr, _8x8_1);
			break;
		}//end switch _intraChrPredMode...
	}//end if usePrevPred...
	else
		pMb->_intraChrPredMode = GetIntra8x8ChrPredAndMode(pMb, _Cb, _Cr, _RefCb, _RefCr, _8x8_0, _8x8_1);

	_Cb->Read(*(_RefCb));
	_RefCb->Sub8x8(*(_8x8_0));
	_Cr->Read(*(_RefCr));
	_RefCr->Sub8x8(*(_8x8_1));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the differnce Lum and Chr after prediction.
	MacroBlockH264::LoadBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY);

	/// ------------------ Transform & Quantisation --------------------------------------------
	/// Implement the forward and feedback loop into the temp blks. The block coeffs are still 
  /// required for the context-aware vlc coding and therefore the temporary working blocks are
  /// used in the feedback loop. The mb QP will change during the TransAndQuantIntra16x16MBlk() 
  /// method call.
	if (pMb->_mbPartPredMode == MacroBlockH264::Intra_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantIntra16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Feedback loop -------------------------------------------------------

	/// --------------------- Image Storing into Ref -----------------------------------------
	/// Fill the ref (difference) lum and chr from all the non-DC 4x4 
	/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
	MacroBlockH264::StoreBlks(pMb, _RefLum, lOffX, lOffY, _RefCb, _RefCr, cOffX, cOffY, 1);

	/// --------------------- Add the prediction ---------------------------------------------
	/// Lum.
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
	_RefLum->Add16x16WithClip255(*(_16x16));	///< Add pred to ref Lum and leave result in ref img.
	/// Cb.
	_RefCb->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCb->Add8x8WithClip255(*(_8x8_0));
	/// Cr.
	_RefCr->SetOverlayDim(8, 8);
	_RefCr->SetOrigin(cOffX, cOffY);
	_RefCr->Add8x8WithClip255(*(_8x8_1));

	/// Distortion with Lum input was calculated in the TransAndQuantIntra16x16MBlk() method. 

	  /// ------------------ Set patterns and type -----------------------------------------------
	  /// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	  /// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate and store results -----------------------------------------
	/// Store rate for this quant value.
	if (withDR == 1) ///< For withDR = 2, no rate calculation is done.
	{
		if (_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE) ///< Requires coeff bits without the mb header bits.
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerCoeffBitCounter(pMb);
		else
			pMb->_rate[pMb->_mbEncQP] = MacroBlockLayerBitCounter(pMb);
	}//end if withDR...

	return(pMb->_rate[pMb->_mbEncQP]);
}//end ProcessIntraMbImplStd.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
and ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisation(MacroBlockH264* pMb)
{
	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs of lum and chr are zeroed. {67..69} The AC coeffs of the Chr DC 
	/// 2x2 coeffs additionally zeroed. {70..84} AC coeffs of the Lum DC coeffs additionally 
	/// zeroed. {85} DC coeff of the Chr DC 2x2 coeffs zeroed. {86} DC coeff of the Lum DC 
	/// coeffs zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	int lumDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 69)  ///< Include AC coeff of Chr DC for QP = {67..69}.
	{
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 84)  ///< Include AC coeffs of Lum DC and all AC coeffs of Chr DC for QP = {70..84}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 3; ///< Not the Chr DC term.
		lumDcCoeffZeroed = pMb->_mbEncQP - 69;
	}//end else if _mbEncQP...
	else if (pMb->_mbEncQP <= 85)  ///< Include all Chr DC coeffs but only AC coeffs of Lum DC for QP = {85}.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4; ///< ...and Chr DC term.
		lumDcCoeffZeroed = 15;
	}//end else if _mbEncQP...
	else  ///< All zeroed for QP = {86} and above.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
		lumDcCoeffZeroed = 16;
	}//end else...

	int startPos4x4 = 16 - acCoeffZeroed;
	int startChrDcPos2x2 = 4 - chrDcCoeffZeroed;
	int startLumDcPos4x4 = 16 - lumDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_DC; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_LUM_DC) && (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else if ((blk == MBH264_CB_DC) || (blk == MBH264_CR_DC)) ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startChrDcPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else if blk...
		else ///< if(blk == MBH264_LUM_DC) Lum DC AND zero'ing required.
		{
			if (lumDcCoeffZeroed)
			{
				for (i = startLumDcPos4x4; i < 16; i++)
				{
					if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ4x4[i]] = 0;
				}//end for i...
			}//end if lumDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisation.

/** Extreme quantisation for large QP values by zeroing coeffs.
For mb QP values set to greater than the max for the H.264 standard, zero the coeffs in
an ordered manner. This method must be called after the forward transform and quantisation
but before the inverse process. Used for code factoring. Ver 2 optimises the process used
in the original version.
@param pMb	: Macroblock to operate on.
@return		  : none.
*/
void H264v2Codec::CoeffZeroingQuantisationVer2(MacroBlockH264* pMb)
{
	//////////////////////////////////////////////////////////////////////////
	  // if(pMb->_mbEncQP <= H264V2_MAX_QP + 15) return; ///< Why are we here?
	//////////////////////////////////////////////////////////////////////////

	int blk, i;
	const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
	const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

	/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
	/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that 
	/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71} 
	/// Lum DC coeffs additionally zeroed.
	int acCoeffZeroed = 15; ///< By default.
	int chrDcCoeffZeroed = 0;
	if (pMb->_mbEncQP <= (H264V2_MAX_QP + 15))
		acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
	else if (pMb->_mbEncQP <= 70)  ///< Include Chr DC coeffs for QP = {67..70}.
		chrDcCoeffZeroed = pMb->_mbEncQP - 66;
	else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
	{
		acCoeffZeroed = 16;
		chrDcCoeffZeroed = 4;
	}//end else...
	int startPos4x4 = 16 - acCoeffZeroed;
	int startPos2x2 = 4 - chrDcCoeffZeroed;

	/// Zero coeff in the mb according to the QP rules above.
	for (blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		short* pB = pBlk->GetBlk();

		if ((blk != MBH264_CB_DC) && (blk != MBH264_CR_DC))  ///< Exclude Chr DC blks.
		{
			for (i = startPos4x4; i < 16; i++)
			{
				if (pB[pZZ4x4[i]])  ///< Only need to change coeffs that are not already zero.
					pB[pZZ4x4[i]] = 0;
			}//end for i...
		}//end if blk...
		else  ///< Chr DC blks AND zero'ing required.
		{
			if (chrDcCoeffZeroed)
			{
				for (i = startPos2x2; i < 4; i++)
				{
					if (pB[pZZ2x2[i]])  ///< Only need to change coeffs that are not already zero.
						pB[pZZ2x2[i]] = 0;
				}//end for i...
			}//end if chrDcCoeffZeroed...
		}//end else...

	}//end for blk...

}//end CoeffZeroingQuantisationVer2.

/** The absolute min bit encoding of a Std Intra macroblock.
Set and measure the encoding for a min bit implementation of the std Intra
macroblock. This only includes DC prediction and all residual DC and AC
coeffs are zero'ed. QP is set to max. Return the bit cost.
@param pMb	: Macroblock to operate on.
@return		  : Bit cost.
*/
int H264v2Codec::ProcessIntraMbImplStdMin(MacroBlockH264* pMb)
{
	int rate = 0;
	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all intra macroblocks.
	pMb->_mbQP = H264V2_MAX_QP;
	pMb->_skip = 0;
	pMb->_intraFlag = 1;

	///------------------- Image prediction and loading ----------------------------------------
	/// Currently only Intra 16x16 mode implemented. 
	pMb->_mbPartPredMode = MacroBlockH264::Intra_16x16;

	/// Predict the input from the previously decoded neighbour ref macroblocks then subtract the
	/// prediction from the input.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
	/// Force the selection to DC Lum prediction for all macroblocks.
	pMb->_intra16x16PredMode = MacroBlockH264::Intra_16x16_DC;
	GetIntra16x16LumDCPred(pMb, _RefLum, _16x16);

	_RefLum->Write16x16(*(_16x16)); ///< Write the prediction into the ref.

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);

	pMb->_intraChrPredMode = MacroBlockH264::Intra_Chr_DC;
	GetIntra8x8ChrDCPred(pMb, _RefCb, _8x8_0);
	GetIntra8x8ChrDCPred(pMb, _RefCr, _8x8_1);

	_RefCb->Write8x8(*(_8x8_0));
	_RefCr->Write8x8(*(_8x8_1));

	/// Clear all mb coeffs for encoding. Implies all difference DC and AC coeffs are zero.
	for (int blk = 0; blk < MBH264_NUM_BLKS; blk++)
	{
		BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		(pBlk->GetBlkOverlay())->Clear();
		pBlk->SetNumCoeffs(0);
	}//end for blk...

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. For Intra slices
	/// no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;
	if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	///< Previous macroblock within same slice.
			pMb->_mb_qp_delta = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mb_qp_delta = pMb->_mbQP - _slice._qp;

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// ------------------ Calc the Rate --------------------------------------------------------
	rate = MacroBlockLayerBitCounter(pMb);

	return(rate);
}//end ProcessIntraMbImplStdMin.

/** Encode the image data for Inter pictures.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplStdVer1::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Create an img to capture the difference between the input img 
  /// and the motion comp pred img. The collection is done per mb and dumped to file after.
  //int selectedFrameNum = 0;
  ////int selectedFrameList[15] = {19, 78, 93, 148, 152, 154, 156, 173, 182, 194, 204, 207, 213, 216, 221}; ///< Foreman
  ////int selectedFrameList[7] = {24, 62, 126, 184, 210, 258, 278}; ///< Mobile
  //int selectedFrameList[9] = {15, 24, 52, 114, 124, 152, 226, 256, 288}; ///< Soccer
  //for(int i = 0; i < 9; i++)
  //{
  //  if(_codec->_frameNum == selectedFrameList[i])
  //    selectedFrameNum = _codec->_frameNum;
  //}//end for i...

  //short* pDiffLum = NULL;
  //short* pDiffCb  = NULL;
  //short* pDiffCr  = NULL;
  //OverlayMem2Dv2* diffLum	= NULL;
  //OverlayMem2Dv2* diffCb	= NULL;
  //OverlayMem2Dv2* diffCr	= NULL;

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  pDiffLum = new short[(_codec->_lumWidth * _codec->_lumHeight) + 2*(_codec->_chrWidth * _codec->_chrHeight)];
  //  pDiffCb = &(pDiffLum[_codec->_lumWidth * _codec->_lumHeight]);
  //  pDiffCr = &(pDiffLum[(_codec->_lumWidth * _codec->_lumHeight) + (_codec->_chrWidth * _codec->_chrHeight)]);

	 // diffLum	= new OverlayMem2Dv2(pDiffLum, _codec->_lumWidth, _codec->_lumHeight, _codec->_lumWidth, _codec->_lumHeight);
	 // diffCb	= new OverlayMem2Dv2(pDiffCb, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);
	 // diffCr	= new OverlayMem2Dv2(pDiffCr, _codec->_chrWidth, _codec->_chrHeight, _codec->_chrWidth, _codec->_chrHeight);

  //  /// Copy the input img into the diff img from where the comp pred img will be subtracted.
  //  _codec->_Lum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  _codec->_Cb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Cr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  _codec->_Lum->SetOrigin(0, 0);
  //  _codec->_Cb->SetOrigin(0, 0);
  //  _codec->_Cr->SetOrigin(0, 0);

  //  diffLum->Write(*_codec->_Lum);
  //  diffCb->Write(*_codec->_Cb);
  //  diffCr->Write(*_codec->_Cr);

  //  /// Restore blk dimensions.
  //  diffLum->SetOverlayDim(16, 16);
  //  diffCb->SetOverlayDim(8, 8);
  //  diffCr->SetOverlayDim(8, 8);
  //  _codec->_Lum->SetOverlayDim(4, 4);
  //  _codec->_Cb->SetOverlayDim(4, 4);
  //  _codec->_Cr->SetOverlayDim(4, 4);
  //}//end if _frameNum...
  /////////////////////////////////////////////////////////////////////////////////////////////

	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		/////////////////////////////////////////////////////////////////////////////////////////////
		/// Research Data Collection: Mb data capture.
		//if(_codec->_frameNum == selectedFrameNum)
		//{
		   // diffLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // diffCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // diffCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  _codec->_RefLum->SetOverlayDim(16, 16);
		//  _codec->_RefCb->SetOverlayDim(8, 8);
		//  _codec->_RefCr->SetOverlayDim(8, 8);
		   // _codec->_RefLum->SetOrigin(pMb->_offLumX, pMb->_offLumY);
		   // _codec->_RefCb->SetOrigin(pMb->_offChrX, pMb->_offChrY);
		   // _codec->_RefCr->SetOrigin(pMb->_offChrX, pMb->_offChrY);

		//  diffLum->Sub(*_codec->_RefLum);
		//  diffCb->Sub(*_codec->_RefCb);
		//  diffCr->Sub(*_codec->_RefCr);

		//  _codec->_RefLum->SetOverlayDim(4, 4);
		//  _codec->_RefCb->SetOverlayDim(4, 4);
		//  _codec->_RefCr->SetOverlayDim(4, 4);
		//}//end if _frameNum...
		/////////////////////////////////////////////////////////////////////////////////////////////

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this macroblock as the median of the neighbourhood 
		/// vectors and subtract it from the macroblock vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
		pMb->_mbQP = _codec->_slice._qp;
		_codec->ProcessInterMbImplStd(pMb, addRef, 0);

	}//end for mb...

  /////////////////////////////////////////////////////////////////////////////////////////////
  /// Research Data Collection: Dump to file and clean up in reverse order.

  //if(_codec->_frameNum == selectedFrameNum)
  //{
  //  char* filenameBase = "c:/keithf/Videos/StdTestVideos/Soccer352x288_30fps";
  //  char  sQP[8];
  //  char  sFrmNum[16];
  //  char sFilename[512];
  //  char sFilenameFinal[512];

  //  strcpy(sFilename, (const char*)filenameBase);
  //  strcat(sFilename, (const char*)"_qp");
  //  strcat(sFilename, (const char*)(_itoa(_codec->_slice._qp, sQP, 10)));
  //  strcat(sFilename, (const char*)"_frm");
  //  strcat(sFilename, (const char*)(_itoa(selectedFrameNum, sFrmNum, 10)));

  //  diffLum->SetOverlayDim(_codec->_lumWidth, _codec->_lumHeight);
  //  diffLum->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_lum.csv");
  //  diffLum->Dump(diffLum, sFilenameFinal, "");

  //  diffCb->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCb->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cb.csv");
  //  diffLum->Dump(diffCb, sFilenameFinal, "");

  //  diffCr->SetOverlayDim(_codec->_chrWidth, _codec->_chrHeight);
  //  diffCr->SetOrigin(0, 0);
  //  strcpy(sFilenameFinal, (const char*)sFilename);
  //  strcat(sFilenameFinal, (const char*)"_cr.csv");
  //  diffLum->Dump(diffCr, sFilenameFinal, "");
  //}//end if _frameNum...

  //if(diffCr != NULL)
  //  delete diffCr;
  //if(diffCb != NULL)
  //  delete diffCb;
  //if(diffLum != NULL)
  //  delete diffLum;

  //if(pDiffLum != NULL)
  //  delete[] pDiffLum;
  /////////////////////////////////////////////////////////////////////////////////////////////

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplStdVer1::Encode.

/** The forward and inverse loop of a Std Inter macroblock.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param usePrevPred  : Use previous prediction mode.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

	/// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------- Zero Coeffs for QP > H264V2_MAX_QP -------------------------------------
	if (pMb->_mbEncQP > H264V2_MAX_QP)
		CoeffZeroingQuantisationVer2(pMb);
	/*
	  {
		int blk, i;
		const int *pZZ4x4 = CAVLCH264Impl::zigZag4x4Pos;
		const int *pZZ2x2 = CAVLCH264Impl::zigZag2x2Pos;

		/// There are 16 (4x4) AC coeffs per blk and the _mbEncQP value indicates how many of
		/// these are to be zeroed in reverse zig-zag order. _mbEncQP = {52..66} implies that
		/// {1..15} AC coeffs are zeroed. {67..70} Chr DC 2x2 coeffs additionally zeroed. {71}
		/// Lum DC coeffs additionally zeroed.
		int acCoeffZeroed     = 15; ///< By default.
		int chrDcCoeffZeroed  = 0;
		if( pMb->_mbEncQP <= (H264V2_MAX_QP + 15) )
		  acCoeffZeroed = pMb->_mbEncQP - H264V2_MAX_QP;
		else if( pMb->_mbEncQP <= 70 )  ///< Include Chr DC coeffs for QP = {67..70}.
		{
		  chrDcCoeffZeroed = pMb->_mbEncQP - 66;
		}//end else if _mbEncQP...
		else ///< if( pMb->_mbEncQP == 71 )  Include Lum and Chr DC coeffs.
		{
		  acCoeffZeroed     = 16;
		  chrDcCoeffZeroed  = 4;
		}//end else...
		int startPos4x4 = 16 - acCoeffZeroed;
		int startPos2x2 = 4 - chrDcCoeffZeroed;

		/// Zero coeff in the mb according to the QP rules above.
		  for(blk = MBH264_LUM_0_0; blk < MBH264_NUM_BLKS; blk++)
		  {
			  BlockH264* pBlk = pMb->_blkParam[blk].pBlk;
		  short* pB = pBlk->GetBlk();

		  if( (blk != MBH264_CB_DC) && (blk != MBH264_CR_DC) )  ///< Exclude Chr DC blks.
		  {
			for(i = startPos4x4; i < 16; i++)
			{
			  if( pB[pZZ4x4[i]] )  ///< Only need to change coeffs that are not already zero.
				pB[pZZ4x4[i]] = 0;
			}//end for i...
		  }//end if blk...
		  else  ///< Chr DC blks AND zero'ing required.
		  {
			if(chrDcCoeffZeroed)
			{
			  for(i = startPos2x2; i < 4; i++)
			  {
				if( pB[pZZ2x2[i]] )  ///< Only need to change coeffs that are not already zero.
				  pB[pZZ2x2[i]] = 0;
			  }//end for i...
			}//end if chrDcCoeffZeroed...
		  }//end else...

		  }//end for blk...

	  }//end if _mbEncQP...
	*/
	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
		if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
			InverseTransAndQuantInter16x16MBlk(pMb, 1);

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));            ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the Distortion & Rate and store results ----------------------------------
	/// Store distortion for this quant value.
	if (withDR)
	{
		/// Calc distortion with Input. If there was a coded blk pattern then compare with temp img else
	  /// with the unaltered ref img.
		OverlayMem2Dv2* pLI = _RefLum;
		OverlayMem2Dv2* pCbI = _RefCb;
		OverlayMem2Dv2* pCrI = _RefCr;
		if (pMb->_coded_blk_pattern)
		{
			pLI = _16x16;
			pCbI = _8x8_0;
			pCrI = _8x8_1;
		}//end else if _coded_blk_pattern...

#ifdef USE_ABSOLUTE_DIFFERENCE
		distortion += pLI->Tad16x16(*_Lum);	///< Total abs distortion between Ref and input Lum.
		distortion += pCbI->Tad8x8(*_Cb);
		distortion += pCrI->Tad8x8(*_Cr);
#else
		distortion += pLI->Tsd16x16(*_Lum);	///< Total square distortion between Ref and input Lum.
		distortion += pCbI->Tsd8x8(*_Cb);
		distortion += pCrI->Tsd8x8(*_Cr);
#endif
    /// Modify the distortion with the region of interest map.
    distortion = ROIDistortion(pMb->_mbIndex, distortion);
		pMb->_distortion[pMb->_mbEncQP] = distortion;

		//    if(!pMb->_skip)
		//		  rate = MacroBlockLayerBitCounter(pMb);
		//    else
		if (pMb->_skip)
		{
			/// Ensure coeffs settings are synchronised for future use by neighbours.
			for (int i = 1; i < MBH264_NUM_BLKS; i++)
				pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
		}//end if _skip...

	//    pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	/// Store rate for this quant value if required.
	if ((withDR == 1) && (!pMb->_skip)) ///< For withDR = 2, no rate calculation is done.
	{
		rate = MacroBlockLayerBitCounter(pMb);
		pMb->_rate[pMb->_mbEncQP] = rate;
	}//end if withDR...

	return(rate);
}//end ProcessInterMbImplStd.

/** The forward and inverse loop of a Std Inter macroblock with a Dmax criterion.
Does NOT include motion prediction and compensation. Assumes these are
already set before called. Code factoring usage. Includes reading the
input image, IT, quantisation, vlc encoding and determining coding
patterns, type, etc. Includes accumulation of the frame MAD measure.
Return the bit cost.
@param pMb		      : Macroblock to operate on.
@param withDR	      : With distortion-rate calculations. If = 2 then distortion only (no rate calc.)
@param Dmax         : Max distortion for this mb.
@param minQP        : Lower limit for the QP descent.
@return				      : Bits consumed or 0 for skipped mb.
*/
int H264v2Codec::ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP)
{
	/// NB: _mbQP must be correctly defined before this method is called.
	pMb->_mbEncQP = pMb->_mbQP;  ///< mbQP may be altered in this method therefore store the requested QP.

	if (pMb->_mbQP > H264V2_MAX_QP) ///< Special conditions apply for out of range QP values.
		pMb->_mbQP = H264V2_MAX_QP;

	/// The delta QP for a mb is constrained to {-26...25}. 
	int q = pMb->_mbQP;

	int prevQP = GetPrevMbQP(pMb);
	int lowQP = prevQP - 26;
	if (lowQP < minQP) lowQP = minQP;
	int highQP = prevQP + 25;
	if (highQP > H264V2_MAX_QP) highQP = H264V2_MAX_QP;
	if (q < lowQP) q = lowQP;
	else if (q > highQP) q = highQP;
	pMb->_mbQP = q;

	int distortion = 0;
	int rate = 0;

	int lOffX = pMb->_offLumX;
	int lOffY = pMb->_offLumY;
	int cOffX = pMb->_offChrX;
	int cOffY = pMb->_offChrY;

	/// Base settings for all inter macroblocks.
	pMb->_skip = 0;
	pMb->_intraFlag = 0;

	/// Subtract the ref (compensated) macroblock from the input macroblock and place it in the temp image blocks.

	/// Lum...
	_RefLum->SetOverlayDim(16, 16);
	_RefLum->SetOrigin(lOffX, lOffY);   ///< Align the Ref Lum img block with this macroblock.
	_Lum->SetOverlayDim(16, 16);
	_Lum->SetOrigin(lOffX, lOffY);		  ///< Align the Lum img block with this macroblock.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);

	_Lum->Read(*(_16x16));				      ///< Read from input Lum into temp.
	_16x16->Sub16x16(*(_RefLum));	      ///< Subtract ref Lum and leave result in temp.

  /// Fame luma signal MAD and MSD accumulation. These variables were cleared before processing the frame.
  /// The calculation is only defined within the mb and from col 1 row 0 onwards, the first pel in each row
  /// is then compared with the one above.
	if (withDR)
	{
		for (int r = 0; r < 16; r++)
			for (int c = 0; c < 16; c++)
			{
				if (r || c)  ///< Not (0,0)
				{
					int curr, prev;
					curr = _16x16->Read(c, r);
					if (c)
						prev = _16x16->Read(c - 1, r); ///< Left.
					else
						prev = _16x16->Read(c, r - 1); ///< Above.

					_frameMAD += DISTORTIONABSDIFF(curr, prev);
					_frameMSD += DISTORTIONSQRDIFF(curr, prev);
				}//end if r...
			}//end for r & c...

		_frameMAD_N += 255;
	}//end if withDR...

	  /// ... and Chr components.
	_RefCb->SetOverlayDim(8, 8);
	_RefCr->SetOverlayDim(8, 8);
	_RefCb->SetOrigin(cOffX, cOffY);
	_RefCr->SetOrigin(cOffX, cOffY);
	_Cb->SetOverlayDim(8, 8);
	_Cb->SetOrigin(cOffX, cOffY);
	_Cr->SetOverlayDim(8, 8);
	_Cr->SetOrigin(cOffX, cOffY);
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);

	_Cb->Read(*(_8x8_0));
	_8x8_0->Sub8x8(*(_RefCb));
	_Cr->Read(*(_8x8_1));
	_8x8_1->Sub8x8(*(_RefCr));

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
  /// Includes the distortion calc and the inverse quant and transform to the temp blks. For 
  /// extended range QP > H264V2_MAX_QP the appropriate coeffs are zeroed. 
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		pMb->_distortion[pMb->_mbEncQP] = TransAndQuantInter16x16MBlk(pMb, Dmax, lowQP);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the delta quantisation parameter. Note that it is not coded onto the bit stream
	/// if all 4x4 blocks have no coeffs (not coded). The quant param for this macroblock is then
	/// assumed to be the same as the previous non-skipped macroblock within the same slice. This
	/// works because multiplying any quant param by zero is still zero. NB: This alters the _mbQP
  /// value therefore the original QP used for the encoding is stored in _mbEncQP.
	pMb->_mb_qp_delta = GetDeltaQP(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	  /// ------------------ Calc distortion from feedback loop ----------------------------------
	  /// Implement the feedback loop into the ref image. The block coeffs are still required for 
	  /// the context-aware vlc coding and therefore the temporary working blocks within the macroblock 
	  /// class are used for this feedback loop.
	if (pMb->_coded_blk_pattern)
	{
		/// --------------------- Inverse Transform & Quantisation -------------------------------
	/// The inverse to the temp blks was included in the TransAndQuantInter16x16MBlk() method above.

		/// --------------------- Image Storing into Ref -----------------------------------------
		/// Fill the temp image (difference) colour components from all the non-DC 4x4 
		/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
		MacroBlockH264::StoreBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0, 1);

		/// --------------------- Add the prediction ---------------------------------------------
		/// Lum.
		_RefLum->SetOverlayDim(16, 16);
		_RefLum->SetOrigin(lOffX, lOffY);			    ///< Align the Ref Lum img block with this macroblock.
		_16x16->SetOverlayDim(16, 16);
		_16x16->SetOrigin(0, 0);
		_16x16->Add16x16WithClip255(*(_RefLum));  ///< Add ref Lum and leave result in temp img.
		if (addRef)
			_RefLum->Write16x16(*(_16x16));

		/// Cb.
		_RefCb->SetOverlayDim(8, 8);
		_RefCb->SetOrigin(cOffX, cOffY);
		_8x8_0->SetOverlayDim(8, 8);
		_8x8_0->SetOrigin(0, 0);
		_8x8_0->Add8x8WithClip255(*(_RefCb));
		if (addRef)
			_RefCb->Write8x8(*(_8x8_0));
		/// Cr.
		_RefCr->SetOverlayDim(8, 8);
		_RefCr->SetOrigin(cOffX, cOffY);
		_8x8_1->SetOverlayDim(8, 8);
		_8x8_1->SetOrigin(0, 0);
		_8x8_1->Add8x8WithClip255(*(_RefCr));
		if (addRef)
			_RefCr->Write8x8(*(_8x8_1));

	}//end if _coded_blk_pattern...

	/// ------------------ Calc the rate and store results ----------------------------------
	if (withDR && pMb->_skip)
	{
		/// Ensure coeffs settings are synchronised for future use by mb neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end if withDR...

	/// Store rate for this quant value if required.
	if (!pMb->_skip)
	{
		if ((withDR == 1) || (withDR == 3)) ///< For withDR = 2, no rate calculation is done.
		{
			rate = MacroBlockLayerCoeffBitCounter(pMb);
			pMb->_rate[pMb->_mbEncQP] = rate;
		}//end if withDR...
	}//end if !skip...

	return(rate);
}//end ProcessInterMbImplStd.

/// Does NOT include motion prediction and compensation. Assumes these mb members are already set before called.
int H264v2Codec::ProcessInterMbImplStdMin(MacroBlockH264* pMb)
{
	/// Set the difference to the compensated reference to zero and therefore no operation needs to be
	/// performed on the ref. Zero and clear all blocks.

	  /// NB: _mbQP must be correctly defined before this method is called.
	int rate = 0;

	/// Base settings for all inter macroblocks.
	pMb->_intraFlag = 0;
	pMb->_skip = 0;

	/// Clear the delta quantisation parameter and set the _mbQP to the same as the previous non-skipped mb. The
  /// _mbQP does not have any impact because all coeffs are set to zero.
	pMb->_mb_qp_delta = 0;
	/// Find the previous non-skipped macroblock.
	int prevMbIdx = pMb->_mbIndex - 1;
	/// Re-align the quantisation param for future delta qp calculations.
	if (prevMbIdx >= 0)
	{
		if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
			pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
		else
			pMb->_mbQP = _slice._qp;
	}//end if prevMbIdx...
	else
		pMb->_mbQP = _slice._qp;

	/// Force all values to zero before encoding.
	_16x16->SetOverlayDim(16, 16);
	_16x16->SetOrigin(0, 0);
	_16x16->Clear();
	_8x8_0->SetOverlayDim(8, 8);
	_8x8_0->SetOrigin(0, 0);
	_8x8_0->Clear();
	_8x8_1->SetOverlayDim(8, 8);
	_8x8_1->SetOrigin(0, 0);
	_8x8_1->Clear();

	/// Fill all the non-DC 4x4 blks (Not blks = -1, 17, 18) of the macroblock blocks with 
	/// the residual image colour components (after motion compensation/prediction).
	MacroBlockH264::LoadBlks(pMb, _16x16, 0, 0, _8x8_0, _8x8_1, 0, 0);

	/// ------------------ Transform & Quantisation --------------------------------------------
	if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
		TransAndQuantInter16x16MBlk(pMb);

	/// ------------------ Set patterns and type -----------------------------------------------
	/// Determine the coded Lum and Chr patterns. The _codedBlkPatternLum, _codedBlkPatternChr 
	/// and _coded_blk_pattern members are set.
	MacroBlockH264::SetCodedBlockPattern(pMb);

	/// Determine the macroblock type. From the prediction modes and patterns set the 
	/// _mb_type member.
	MacroBlockH264::SetType(pMb, _slice._type);

	/// Only Inter_16x16 mode is currently implemented so only 1 motion vector is 
	/// checked for the macroblock skip mode. If motion is zero then mb is skipped.
	if (pMb->_coded_blk_pattern == 0)
	{
		/// First set of conditions for skip are dependent on a zero 16x16 single motion vector.
		if (MacroBlockH264::SkippedZeroMotionPredCondition(pMb))
		{
			if ((pMb->_mvX[MacroBlockH264::_16x16] == 0) && (pMb->_mvY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end if SkippedZeroMotionPredCondition...
		/// Second condition is dependent on the previously calculated median difference motion vector.
		else
		{
			if ((pMb->_mvdX[MacroBlockH264::_16x16] == 0) && (pMb->_mvdY[MacroBlockH264::_16x16] == 0))
				pMb->_skip = 1;
		}//end else...
	}//end _coded_blk_pattern...

	if (!pMb->_skip)
		rate = MacroBlockLayerBitCounter(pMb);
	else
	{
		/// Ensure coeffs settings are synchronised for future use by neighbours.
		for (int i = 1; i < MBH264_NUM_BLKS; i++)
			pMb->_blkParam[i].pBlk->SetNumCoeffs(0);
	}//end else...

	pMb->_rate[0] = rate;

	return(rate);
}//end ProcessInterMbImplStdMin.

/** Calc delta QP based on macroblock QP.
The coded block pattern, _intraFlag and _mbQP values must be correctly set before calling this
method. The _skip mode for P mbs alters the _mbQP value.
@param pMb    : Macroblock to operate on.
@return       : Delta QP for these mb parameters.
*/
int H264v2Codec::GetDeltaQP(MacroBlockH264* pMb)
{
	int deltaQP = 0;

	/// Find the previous non-skipped macroblock. For Intra slices no previous macroblocks are skipped.
	int prevMbIdx = pMb->_mbIndex - 1;

	if (pMb->_coded_blk_pattern || pMb->_intraFlag)
	{
		if (prevMbIdx >= 0)	///< Previous macroblock is within the image boundaries.
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				deltaQP = pMb->_mbQP - _pMb[prevMbIdx]._mbQP;
			else
				deltaQP = pMb->_mbQP - _slice._qp;
		}//end if prevMbIdx...
		else
			deltaQP = pMb->_mbQP - _slice._qp;
	}//end if _coded_blk_pattern...
	else
	{
		/// Re-align the quantisation param for future delta qp calculations.
		if (prevMbIdx >= 0)
		{
			if (pMb->_slice == _pMb[prevMbIdx]._slice)	/// Previous macroblock within same slice.
				pMb->_mbQP = _pMb[prevMbIdx]._mbQP;
			else
				pMb->_mbQP = _slice._qp;
		}//end if prevMbIdx...
		else
			pMb->_mbQP = _slice._qp;
	}//end else...

	return(deltaQP);
}//end GetDeltaQP.

/** Get the previous macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Previous Mb QP.
*/
int H264v2Codec::GetPrevMbQP(MacroBlockH264* pMb)
{
	int prevMbIdx = pMb->_mbIndex - 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((prevMbIdx >= 0) && (pMb->_slice == _pMb[prevMbIdx]._slice))
		return(_pMb[prevMbIdx]._mbQP);
	else
		return(_slice._qp);
}//end GetPrevMbQP.


/** Get the next macroblock QP value.
Picture and slice boundaries are considered in returning the
neighbouring mb QP value.
@param pMb    : Macroblock to operate on.
@return       : Next Mb QP.
*/
int H264v2Codec::GetNextMbQP(MacroBlockH264* pMb)
{
	int nextMbIdx = pMb->_mbIndex + 1;

	///< Previous macroblock is within the image boundaries and within same slice.
	if ((nextMbIdx < _mbLength) && (pMb->_slice == _pMb[nextMbIdx]._slice))
		return(_pMb[nextMbIdx]._mbQP);
	else
		return(pMb->_mbIndex);
}//end GetPrevMbQP.

/** Encode the image data for Inter pictures with QP adaptation at macroblock level.
Process all macroblocks in order and only write the result to the ref image
space if the writeRef code is set. Bit 1 of writeRef refers to motion compensation
and bit 0 to adding the difference to the ref. The motion estimation process with
its associated data structures is assumed to have been completed before this
method is called. The macroblock obj is prepared for coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 + X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
The macroblock wide _mbPQ is adapted to ensure that the resulting stream will use
no more than allowedBits. This algorithm uses a bisection technique to minimise the
max distortion by adapting the macroblock quant value until the nearest rate to the
total allowable bits is achieved.
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	int mb, bitCount;
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int minMBIndex = len; ///< Mark the macroblock from where min units must be encoded.

	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

  /// Mark this time point for later use.
	int preMotionTime = 0;
	if (_codec->_timeLimitMs)
		preMotionTime = (int)_codec->GetCounter();

	///	---------------------- Motion Vector encoding ---------------------------------------

	/// In this implementation QP adaptation is performed after full motion compensation.
	/// Get the motion vector list to work with. Assume SIMPLE2D type list.
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

	/// Prepare the compensation on a per macroblock basis.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Count the bits used for the motion vectors by iterating through the
	/// macroblocks and encoding the differential motion vector diff (_mvdX,_mvdY). 
  /// Check that there are sufficient bits available for each vector. If not then 
  /// truncate the estimation result and mark all remaining macroblocks as skipped. 
  /// Store the bit cost of the mb with only motion vectors coded in _rate[0].
	int bitCost = 0;
	int mbSkipRun = 0;
	/// Start with all mbs skipped to the end by counting bits for mbSkipRun = len;
	int minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(len);
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Set the mb with the the motion vector, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors and subtract from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		/// Motion compensate the macroblock.
		if (compRef)
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);

		int lclAllowedBits = (allowedBits - bitCost) - minPictureBitsToEnd;	///< So far before encoding this MVD pair.

	  /// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);

		/// For skipped mbs, the previous skipped bit count must be included in the minPictureBitsToEnd.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			lclBitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Are there enough bits left to encode this run + MVD pair?
			if (lclBitCost < lclAllowedBits)
				bitCost += lclBitCost;  ///< Update the accumulator.
			else	///< Truncation condition.
			{
				/// Clean up all remaining macroblocks as skipped and exit. In this implementation
				/// when there are not enough bits to encode all the motion vectors the estimated list
				/// is truncated with [0,0] difference vectors or [0,0] motion with special conditions 
			  /// and re-compensated.
				return(DamageControlMvOnly(allowedBits, bitsUsed));
			}//end else...

			mbSkipRun = 0; ///< Reset.

		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;

		/// Update remaining bits for next mb where all remaining mbs are skipped.
		int mbSkippedToEnd = mbSkipRun + ((len - 1) - mb);
		if (mbSkippedToEnd)
			minPictureBitsToEnd = _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkippedToEnd);
		else
			minPictureBitsToEnd = 0;
	}//end for mb...
  /// Include the last run to the end.
	bitCost += minPictureBitsToEnd;
	if (bitCost >= allowedBits)  ///< ...and check.
		return(DamageControlMvOnly(allowedBits, bitsUsed));
	int minMvBitsToEnd = bitCost;	///< Hold the total motion vector with zero residual bit cost.

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock Q search.
	-------------------------------------------------------------------------------------------
	*/
	/// Initialisation step: 
	  ///		lower(D,R) : QP = H264V2_MAX_QP.
	  /// Note that the D values represent the worst distortion of only one macroblock in the entire
	  /// frame but the R values represent the accumulated rate of all macroblocks.
	int	Dl = 0;
	int	Du = 0;
	int	Rl = 0;
	int	Ru = 0;
	int	R = 0;
	int	D = 0;
	int	Dmax = 0;
	int iterations = 0;
	int	invalidated = 0;
	int mbDmax = 0;

	/// Test QP = H264V2_MAX_QP for all macroblocks and determine if this min possible rate is, at the very 
	/// least, less than the target rate. Damage control is required if not, where minimal encodings
	/// are attempted for the macroblocks. Otherwise, proceed with the initialisation.
	mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		/// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;
		/// Include all macroblocks at the start.
		pMb->_include = 1;
		_pQl[mb] = H264V2_MAX_QP;
		_pQ[mb] = H264V2_MAX_QP;	///< Active quantiser vector is always the lower (max distortion) side.

		/// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
	  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
		Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		if (!pMb->_skip)
		{
			/// Sum of skip run and coded mb bits accumulated.
			Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

		if (pMb->_distortion[H264V2_MAX_QP] > Dl)
		{
			Dl = pMb->_distortion[H264V2_MAX_QP];
			mbDmax = mb;	///< Mark the mb index with the peak distortion.
		}//end if _distortion...

		/// No early exit because damage control uses this result = Rl.

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Set the limits on the number of optimisation iterations by a timer or iteration number. Take into
  /// account the time taken to get to this point from _startTimer but exclude the motion estimation time
  /// as an offset.
	int start = 0;
	int timeOffset = 0;
	int lclIterations = _codec->_interIterations;
	int lclTimeLimit = _codec->_timeLimitMs;  ///< In ms. A zero indicates either no counter available or not set.
	if (lclTimeLimit)
	{
		start = (int)_codec->GetCounter();
		timeOffset = 2 * (preMotionTime - _codec->_startTime);
	}//end if lclTimeLimit...

	  /// Test that there is room to adapt from quant param = H264V2_MAX_QP, else do damage control.
	if (Rl <= allowedBits)
	{

		/// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
		/// Adjust the available bits to be epsilon below allowedBits.
		int closeEnough = allowedBits / 250;	///< 0.4%
		if (closeEnough < 16)
			closeEnough = 16;
		int closeEnoughDist = 8;	///< Sqr error per macroblock.

	  /// Model based faster algorithm to improve on the bi-section method.

		/// Modify the target rate to a close offset on the low rate side.
		int bitTarget = allowedBits - closeEnough;

		/// The worst case at QP = H264V2_MAX_QP uses less bits than allowed so there is some
		/// room to manouver and we can proceed. The upper point is initially not calculated
		/// directly but will hold a valid value during the algorithm convergence after the
		/// first iteration.
		/// The upper point is initiallised to some wild guess.
		Du = 1;									///< Min (im)possible.
		Ru = allowedBits << 8;	///< Some very large number.

		/// Initialisation is complete and the adapting bi-section/power model algorithm starts 
		/// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
		/// or 2) small change in distortion when reducing the interval.
		int done = 0;
		while (!done)
		{
			int prevDmax = Dmax;

			/// Make a prediction assuming a power law model.
			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
			/// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
			if ((Dmax < Du) || (Dmax > Dl))	///< Out of bound.
				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

			/// Encourage the descent direction by adding a decreasing factor to the
			/// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
			Dmax += abs(Dl - Dmax) / 4;

			if ((Dmax < Du) || (Dmax > Dl) || (Dmax == prevDmax))	///< Still out of bound.
				Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

			/// At each macroblock reduce the quant value until the distortion is lower
			/// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector 
			/// as the previous best choice.
			R = 0;
			int firstMbChange = len;
			if (invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
				firstMbChange = 0;
			mbSkipRun = 0;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				/// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
				_pQ[mb] = _codec->GetMbQPBelowDmaxVer2(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, false);
				R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
				if (!pMb->_skip)
				{
					/// Sum of skip run and coded mb bits accumulated.
					R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
					mbSkipRun = 0;
				}//end if !_skip...
				else
					mbSkipRun++;

				/// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points 
				/// for the whole frame. 

			}//end for mb...
	    /// Add last skip run.
			if (mbSkipRun)
				R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

			/// Test the stopping criteria.
			int timeExceeded = 0;
			if (lclTimeLimit)
			{
				int timeSoFar = (int)(_codec->GetCounter()) - start;
				int avgTimePerIteration = timeSoFar / (1 + iterations);
				int timeLimit = lclTimeLimit - timeOffset - avgTimePerIteration;
				if (timeSoFar > timeLimit)
					timeExceeded = 1;
			}//end if lclTimeLimit...

			int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
			int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
			int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
			if ((rBndDiff < (4 * closeEnough)) ||
				((rDiff < closeEnough) || (/*(R <= allowedBits)&&*/(dDiff < closeEnoughDist))) ||
				(iterations > lclIterations) || timeExceeded)
			{
				/// The new point is the preferable point to choose but if the rate is not below allowedBits
				/// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs 
		    /// must be re-processed.
				if (R > allowedBits)
				{
					/// Load the lower vector as it is always below the target rate.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					R = Rl;
					invalidated = 1;
				}//end if R...
				else
					invalidated = 0;

				/// Optimal solution is found.
				done = 1;
			}//end if rDiff...
			else
			{
				if (allowedBits > R)	///< Inner predicted point is now lower point.
				{
					Dl = Dmax;
					Rl = R;
					/// pQ[] is the lower vector. 
					memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
					invalidated = 0;
				}//end if allowedBits...
				else							///< Inner predicted point is now upper point.
				{
					Du = Dmax;
					Ru = R;
					/// pQ[] must be reset to lower vector to maintain a descent convergence.
					memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
					invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
				}//end else...

			}//end else...

			iterations++;
		}//end while !done...

		/// Set the macroblock QP values to their found states.
		if (invalidated)
		{
			for (mb = 0; mb < len; mb++)
			{
				_codec->_pMb[mb]._mbQP = _pQ[mb];
				_codec->_pMb[mb]._mbEncQP = _pQ[mb];
			}//end for mb...
		}//end if invalidated...

		/// All good.
		//sprintf(_codec->_errorInfo, "P-frame: all good Allowed=%d Cost=%d", allowedBits, R);

	}//end if Rl...
	else	///< Damage control.
	{
		bitCost = DamageControl(allowedBits, Rl);

		if (bitCost >= allowedBits) ///< All failed.
			minMBIndex = 0;

		/// Damage control path.
		//sprintf(_codec->_errorInfo, "P-frame: damage control Allowed=%d Cost=%d", allowedBits, bitCost);

	}//end else Damage control...

	/*
	-------------------------------------------------------------------------------------------
	Residual macroblock final encoding.
	-------------------------------------------------------------------------------------------
	*/
	/// Rip through each macroblock as a linear array and process each block within the macroblock.
	/// The _mbEncPQ values have been set in the above encoding.
	mbSkipRun = 0;
	bitCount = 0;
	for (int mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		/// Encode the mbs and add to Ref img until min null mb position.
		if (mb < minMBIndex)
		{
			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
	  //      bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 0);
			bitCount += _codec->ProcessInterMbImplStd(pMb, 1, 1);
		}//end if mb...
		else
			bitCount += _codec->ProcessInterMbImplStdMin(pMb);
		if (!pMb->_skip)
		{
			bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		}//end if !_skip...
		else
			mbSkipRun++;

	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCount += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	*bitsUsed = 0;
	int ret = 1;
	if (bitCount > allowedBits)  ///< Failed to meet bit target.
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bit target unattainable";
		ret = 0;
	}//end if bitCount...

	return(ret);
}//end InterImgPlaneEncoderImplMinMax::Encode.

/** Damage control algorithm for motion vectors only condition.
Clean up all remaining macroblocks as skipped and exit. In this implementation
when there are not enough bits to encode all the motion vectors the estimated list
is truncated with [0,0] difference vectors or [0,0] motion with special conditions
and re-compensated.
@param allowedBits  : Bits to use.
@param bitsUsed     : Bits consumed on the stream.
@return             : 1 = success, 0 = failed.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControlMvOnly(int allowedBits, int* bitsUsed)
{
	int mb;
	/// Stage 1: Start by taking a snapshot of improvement (mostly negative) in distortion between
	/// the current estimated mv and the predicted mv per mb. Count the total bit rate to determine
	/// how far off from the allwedBits these mvs are.
	int len = _codec->_mbLength;
	int bitCost = 0;
	int mbSkipRun = 0;
	for (mb = 0; mb < len; mb++)
	{
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
		pMb->_include = 1;  ///< Default.

		/// Set the mb with the the mv, do the prediction to get the MVD and apply the motion compensation.
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16; ///< Currently only 16x16 mode supported.
		/// Extract the 16x16 vector from the motion estimation result list.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		int topLeftX = pMb->_offLumX;
		int topLeftY = pMb->_offLumY;
		/// Get the predicted motion vector for this mb as the median of the neighbourhood vectors.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

		/// Compensate with the pred mv and measure the mb distortion.
		_codec->_pMotionCompensator->Invalidate();
		_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, predX, predY);
		int distortion = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);

		if ((mvx != predX) || (mvy != predY))  ///< Only if the estimated mv and the pred mv are not already equal.
		{
			_codec->_pMotionCompensator->Invalidate();
			_codec->_pMotionCompensator->Compensate(topLeftX, topLeftY, mvx, mvy);
			pMb->_distortion[0] = pMb->Distortion(_codec->_RefLum, _codec->_RefCb, _codec->_RefCr, _codec->_Lum, _codec->_Cb, _codec->_Cr);
		}//end if mvx...
		else
		{
			/// Estimated mv is equal to pred mv.
			pMb->_distortion[0] = distortion;
			pMb->_include = 0;
		}//end else...

		/// Expected increase in distortion by choosing the pred mv.
		_pDistortionDiff[mb] = distortion - pMb->_distortion[0];

		/// Store the motion vector in the mb.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;
		/// Set the mv difference before processing the mb.
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
		/// Process the compensated mb as motion vector only with zero'ed residual to measure its rate cost.
		int lclBitCost = _codec->ProcessInterMbImplStdMin(pMb);
		/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
		if (!pMb->_skip)
		{
			/// Sum the run and coding bit contributions.
			bitCost += (lclBitCost + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
			mbSkipRun = 0; ///< Reset.
		}//end if !_skip...
		else  ///< Skipped.
			mbSkipRun++;
	}//end for mb...
  /// Add last skip run.
	if (mbSkipRun)
		bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	/// Stage 2: Sub optimal solution proceeds by scanning the next mb with the initial least distortion 
	/// impact after replacing the estimated mv with the pred mv. Continue to replace the mv with the 
	/// pred mv until the accumulated bits are approximately below the allowed bits ignoring the skip run
	/// bit run contribution. Rely on the initial _rate[0] calculation above to guess the rate savings. 
	/// Then re-calculate actual bits at the end to determine whether or not the loop must continue.
	int forceStop = 0;
	while ((bitCost > allowedBits) && !forceStop)
	{
		///--------------------------------------------------------------------------------------
		int bitSavingRequired = bitCost - allowedBits;
		int savedBits = 0;
		while ((savedBits < bitSavingRequired) && !forceStop)
		{
			int currentLowestDistDiff = 0x7FFFFFFF; ///< Very large starting point.
			/// Find the next lowest distortion difference.
			int nextMb = -1;
			for (mb = 0; mb < len; mb++)
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.
				if (pMb->_include && (_pDistortionDiff[mb] < currentLowestDistDiff))
				{
					currentLowestDistDiff = _pDistortionDiff[mb];
					nextMb = mb;
				}//end if _include...
			}//end for mb...

			if (nextMb >= 0) ///< A candidate mb was found.
			{
				/// Approximate the saving by the existing rate[0] value by assuming that
				/// this mb will be skipped. Ignore the savings on the improved skip run.
				savedBits += _codec->_pMb[nextMb]._rate[0];
				/// Exclude from further checks.
				_codec->_pMb[nextMb]._include = 0;
			}//end if nextMb...
			else
				forceStop = 1;

		}//end while savedBits...

		///--------------------------------------------------------------------------------------
		/// Re-process each mb and accumulate the bit cost. All mbs that are not included must
		/// be set to the pred mv. Only those mbs where the mv has changed are re-compensated.
		bitCost = 0;
		mbSkipRun = 0;
		for (mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			/// The pred mv may now be different.
			int predX, predY;
			MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);

			if (!pMb->_include)  ///< Marked as a previously predicted mv and mv was set to pred mv.
			{
				/// Set the result mv list to the pred mv.
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 0, predX);
				_codec->_pMotionEstimationResult->SetSimpleElement(mb, 1, predY);

				/// Check that this mv is the pred mv.
				if ((pMb->_mvX[MacroBlockH264::_16x16] != predX) || (pMb->_mvY[MacroBlockH264::_16x16] != predY))
				{
					/// Re-compensate if it has changed.
					_codec->_pMotionCompensator->Invalidate();
					_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, predX, predY);
				}//end if _mvX...

			}//end if !include...

			/// Store the motion vector and pred mv in the mb.
			int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
			int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
			pMb->_mvX[MacroBlockH264::_16x16] = mvx;
			pMb->_mvY[MacroBlockH264::_16x16] = mvy;
			pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
			pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;
			int r = _codec->ProcessInterMbImplStdMin(pMb);
			/// For non-skipped mbs, the previous skipped bit count must be included in the bit count.
			if (!pMb->_skip)
			{
				/// Sum the run and coding bit contributions.
				bitCost += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun));
				mbSkipRun = 0; ///< Restart
			}//end if !_skip...
			else  ///< Skipped.
				mbSkipRun++;

		}//end for mb...

		/// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

	}//end while bitCost...

	/// Check that a solution is possible.
	if (forceStop)
	{
		*bitsUsed = 0;
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Forced stop - no solution possible";
		return(0); ///< Failed.
	}//end if allowedBits...

	  /// ...and then exit.
	int ret = 1;
	if (bitCost > allowedBits)
	{
		_codec->_errorStr = "[H264Codec::InterImgPlaneEncoderImplMinMax::Encode] Bits exceeded in trucation";
		ret = 0;
	}//end if bitCost...

	*bitsUsed = 0;
	return(ret); ///< Something is coded so it is considered successful.
}//end InterImgPlaneEncoderImplMinMax::DamageControlMvOnly.

/** Damage control algorithm
Their are insufficient bits at the max QP and alternative quantisation approaches are required.
@param  allowedBits : Bits to use.
@param  currBitCost : Bits used so far for the last encoding of mv and max QP
@return             : Bit cost of this implementation.
*/
int H264v2Codec::InterImgPlaneEncoderImplMinMax::DamageControl(int allowedBits, int currBitCost)
{
	///======================================================================================

	/// Sub-optimal Steepest Ascent Algorithm

	int i, mb;
	int len = _codec->_mbLength;
	int bitCost = currBitCost;
	int iterations = 0;

	/// Initialise the ordered mb list where skipped mbs will never become unskipped and can therefore be excluded.
	int listLen = 0;
	for (mb = 0; mb < len; mb++)
	{
		if (!_codec->_pMb[mb]._skip)
			_pMbList[listLen++] = mb;
	}//end for mb...

	while ((bitCost >= allowedBits) && (listLen > 1))
	{
		int predR = bitCost;

		while ((listLen > 1) && (predR >= allowedBits))
		{
			/// Step 1: Order the non-skipped mbs in increasing distortion.

			/// Only included newly skipped and completed mbs from the old list.
			int currListLen = listLen;
			listLen = 0;
			for (i = 0; i < currListLen; i++)
			{
				mb = _pMbList[i];
				if (!_codec->_pMb[mb]._skip && (_codec->_pMb[mb]._mbEncQP < H264V2_MAX_EXT_QP))
					_pMbList[listLen++] = mb;
			}//end for mb...

			/// Bubble sort list in ascending order of distortion.
			int cnt = len;
			while (cnt)
			{
				cnt = 0; ///< Count how many re-orderings occur.
				for (i = 1; i < listLen; i++)
				{
					MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i - 1]]);
					MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
					if (pMb2->_distortion[pMb2->_mbEncQP] < pMb1->_distortion[pMb1->_mbEncQP])
					{
						/// Swap places.
						int tmp = _pMbList[i - 1];
						_pMbList[i - 1] = _pMbList[i];
						_pMbList[i] = tmp;
						cnt++;
					}//end if _distortion...
				}//end for i...
			}//end while cnt...

			/// Step 2: Increase the distortion of mb at the head of the ordered list to just more than the
			/// next one in the list.
			int mb1 = _pMbList[0]; /// Head of ordered list.
			int mb2 = _pMbList[1]; /// Next in ordered list.
			int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			/// For the unusual case where the listLen == 1, set them to the same.
			if (listLen == 1)
				d2 = d1;

			if ((d1 <= d2) && (_codec->_pMb[mb1]._mbEncQP < H264V2_MAX_EXT_QP))
			{
				MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

				predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
				while ((pMb->_distortion[pMb->_mbEncQP] <= d2) && (pMb->_mbEncQP < H264V2_MAX_EXT_QP))
				{
					/// Select new QP.
					switch (pMb->_mbEncQP)
					{
					case 51: pMb->_mbQP = 55; break;
					case 55: pMb->_mbQP = 59; break;
					case 59: pMb->_mbQP = 63; break;
					case 63: pMb->_mbQP = 67; break;
					case 67: pMb->_mbQP = 68; break;
					case 68: pMb->_mbQP = 69; break;
					case 69: pMb->_mbQP = 70; break;
					case 70: pMb->_mbQP = 71; break;
					default: pMb->_mbQP = 71; break;
					}///end switch _mbEncQP...

					_codec->ProcessInterMbImplStd(pMb, 0, 2);

				}//end while _distortion[]...

				/// Add back new bits.
				if (!pMb->_skip)
				{
					pMb->_rate[pMb->_mbEncQP] = _codec->MacroBlockLayerBitCounter(pMb);
					predR += pMb->_rate[pMb->_mbEncQP];
				}//end if !_skip ...

			}//end if d1...

		}//end while listLen...

		/// Step 3: Test the new solution.
		int mbSkipRun = 0;
		bitCost = 0;
		for (int mb = 0; mb < len; mb++)
		{
			MacroBlockH264* pMb = &(_codec->_pMb[mb]);

			pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
			bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
			if (!pMb->_skip)
			{
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				mbSkipRun = 0;
			}//end if !_skip...
			else
				mbSkipRun++;

		}//end for mb...
	  /// Add last skip run.
		if (mbSkipRun)
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		iterations++;
	}//end while bitCost...

	return(bitCost);

	//    if(bitCost >= allowedBits) ///< All failed.
	//		  minMBIndex = 0;

		///======================================================================================
		/*
		/// Sub-optimal Steepest Descent Algorithm

		/// QP = H264V2_MAX_QP for all mbs still uses too many bits so the extended range of QP = {51..71} is
		/// used here to find a near optimal solution.
		int i;
		bitCost = 0;

		/// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		/// Initialise the ordered mb list.
		int listLen = 0;
		mbSkipRun = 0;
		  for(mb = 0; mb < len; mb++)
		  {
		  MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		  _pMbList[listLen++] = mb; ///< Arbitrary order for the mb list.

		  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			  pMb->_mbQP = H264V2_MAX_EXT_QP;

			  /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		  /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			  bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		  if(!pMb->_skip)
		  {
			/// Sum of skip run and coded mb bits accumulated.
			bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			mbSkipRun = 0;
		  }//end if !_skip...
		  else
			mbSkipRun++;

			  /// Early exit if this min point is still not possible.
			  if(bitCost >= allowedBits)
				  break;

		  }//end for mb...
		/// Add last skip run.
		if(mbSkipRun)
		  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		R = 0;
		iterations  = 0;

			/// Only proceed if there is hope.
			if(bitCost < allowedBits)
		{
		  /// Starting from highest distortion and lowest rate, slowly decrease the distortion
		  /// and count the approx bit improvement until a good guess is acheived. Then test the
		  /// guess for the actual improvement. Reverse up the audit trail until it fits.

		  /// Audit trail initialisation. -1 indicates no entry.
		  memset(_pLastMbCoded, 0xFF, len * sizeof(int));
		  int lastMbPos = 0;

		  /// Repeat until the solution converges but limit it to 3 iterations for speed.
		  int prevBitCost = 0;
		  while( (bitCost > prevBitCost) && (iterations < 3) )
		  {
			prevBitCost = bitCost;
			int predR = bitCost;
			/// Make a guess by iteratively adjusting predicted rate predR
			while( (listLen > 1)&&(predR < allowedBits) )
			{
			  /// Step 2: Order the mbs in decreasing distortion.

			  /// Included all mbs from the old list except for those that have decreased down
			  /// to QP = {51}.
			  int currListLen = listLen;
			  listLen = 0;
			  for(i = 0; i < currListLen; i++)
			  {
				mb = _pMbList[i];
				if(_codec->_pMb[mb]._mbEncQP > H264V2_MAX_QP)
				  _pMbList[listLen++] = mb;
			  }//end for mb...

			  /// Bubble sort list in descending order of distortion.
			  int cnt = len;
			  while(cnt)
			  {
				cnt = 0; ///< Count how many re-orderings occur.
				for(i = 1; i < listLen; i++)
				{
				  MacroBlockH264* pMb1 = &(_codec->_pMb[_pMbList[i-1]]);
				  MacroBlockH264* pMb2 = &(_codec->_pMb[_pMbList[i]]);
				  if( pMb2->_distortion[pMb2->_mbEncQP] > pMb1->_distortion[pMb1->_mbEncQP] )
				  {
					/// Swap places.
					int tmp       = _pMbList[i-1];
					_pMbList[i-1] = _pMbList[i];
					_pMbList[i]   = tmp;
					cnt++;
				  }//end if _distortion...
				}//end for i...
			  }//end while cnt...

			  /// Step 3: Decrease the distortion of mb at the head of the ordered list to just less than the
			  /// next one in the list.
			  int mb1 = _pMbList[0]; /// Head of ordered list.
			  int mb2 = _pMbList[1]; /// Next in ordered list.
			  int d1 = _codec->_pMb[mb1]._distortion[_codec->_pMb[mb1]._mbEncQP];
			  int d2 = _codec->_pMb[mb2]._distortion[_codec->_pMb[mb2]._mbEncQP];

			  /// For the unusual case where the listLen == 1, set them to the same.
			  if(listLen == 1)
				d2 = d1;

			  MacroBlockH264* pMb = &(_codec->_pMb[mb1]);  ///< Simplify mb addressing.

			  /// Store the current mb encoding in the audit trail lists.
			  _pLastMbCoded[lastMbPos]  = mb1;
			  _pLastMbQP[lastMbPos++]   = pMb->_mbEncQP;
			  if(lastMbPos >= len) ///< Loop around.
				lastMbPos = 0;

			  R = pMb->_rate[pMb->_mbEncQP];  ///< Remember R at this point in case the loop below does not execute.
			  predR -= pMb->_rate[pMb->_mbEncQP]; ///< Remove old bits before processing.
			  while( (pMb->_distortion[pMb->_mbEncQP] >= d2) && (pMb->_mbEncQP > H264V2_MAX_QP) && ((predR+R) <= allowedBits) )
			  {
				/// Select new QP and process.
				pMb->_mbQP = NextQPDec[pMb->_mbEncQP];
				  R = _codec->ProcessInterMbImplStd(pMb, 0, 1);
			  }//end while _distortion[]...

			  /// Add back new bits.
			  predR += R;

			}//end while listLen...

			/// Step 3: Test the new solution. On exit of the above loop, the approx
			/// bit rate is just too high and therefore the audit trail is used to reverse
			/// until it fits.

			if(lastMbPos != 0)  ///< Back up by 1.
			  lastMbPos--;
			else ///< Wrap around.
			  lastMbPos = len - 1;

			bitCost = predR;  ///< Start with the guess made above.

			while( (bitCost >= allowedBits) && (_pLastMbCoded[lastMbPos] != -1) )
			{
			  _codec->_pMb[_pLastMbCoded[lastMbPos]]._mbEncQP = _pLastMbQP[lastMbPos];
			  _pLastMbCoded[lastMbPos] = -1;  ///< Mark as used goods.
			  if(lastMbPos != 0)  ///< Back up by 1.
				lastMbPos--;
			  else ///< Wrap around.
				lastMbPos = len - 1;

			  mbSkipRun = 0;
				bitCost = 0;
				for(int mb = 0; mb < len; mb++)
				{
				MacroBlockH264* pMb = &(_codec->_pMb[mb]);

				pMb->_mbQP = pMb->_mbEncQP; ///< Restore the QP that the mb was coded with.
				bitCost += _codec->ProcessInterMbImplStd(pMb, 0, 1);
				if(!pMb->_skip)
				{
				  bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				  mbSkipRun = 0;
				}//end if !_skip...
				else
				  mbSkipRun++;

				}//end for mb...
			  /// Add last skip run.
			  if(mbSkipRun)
				bitCost += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			}//end while bitCost...

			iterations++;
		  }//end while bitCost...

		}//end if bitCost...
		else ///< All failed so mark all for min encodings and hope for the best.
		{
			  minMBIndex = 0;
		}//end else...
		*/
		///======================================================================================
		 /*
		 /// Alternating Bi-Section Algorithm.

		 Ru = Rl;  ///< Upper is now QP = {51} determined above.
		 Du = Dl;
		 Rl = 0;
		 Dl = 0;
		 mbDmax = 0;
		 qEnd   = H264V2_MAX_QP;

		 /// Step 1: Test that QP = {71} will fit and set it to the initialisation of the optimisation algorithm.
		 mbSkipRun = 0;
		   for(mb = 0; mb < len; mb++)
		   {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
			   pMb->_mbQP	  = H264V2_MAX_EXT_QP;
			   /// Include all macroblocks at the start.
			   pMb->_include = 1;
			   _pQl[mb]      = H264V2_MAX_EXT_QP;
			   _pQ[mb]	      = H264V2_MAX_EXT_QP;	///< Active quantiser vector is always the lower (max distortion) side.

			   /// Accumulate the rate and find the largest distortion for all mbs. Call returns 0 for skipped mbs. The ref
		   /// holding the compensated motion is not updated with the encoding in this traversal of the mbs.
			   Rl += _codec->ProcessInterMbImplStd(pMb, 0, 1);
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			   if(pMb->_distortion[H264V2_MAX_EXT_QP] > Dl)
			   {
				   Dl = pMb->_distortion[H264V2_MAX_EXT_QP];
				   mbDmax = mb;	///< Mark the mb index with the peak distortion.
			   }//end if _distortion...

			   /// Early exit if this min point is still not possible. Mark all as min encodings and hope it fits.
			   if(Rl > allowedBits)
		   {
				   minMBIndex = 0;
				   break;
		   }//end if Rl...

		   }//end for mb...
		 /// Add last skip run.
		 if(mbSkipRun)
		   Rl += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

		 /// Step 2: Proceed with optimisation algorithm with QP = {51..71}
		 if(Rl < allowedBits)
		 {
			   /// Create an epsilon at 0.4% of the available bits with a min limit of 16 bits.
			   /// Adjust the available bits to be epsilon below allowedBits.
			   int closeEnough = allowedBits/250;	///< 0.4%
			   if(closeEnough < 16)
				   closeEnough = 16;
			   int closeEnoughDist = 8;	///< Sqr error per macroblock.

		   /// Model based faster algorithm to improve on the bi-section method.

			   /// Modify the target rate to a close offset on the low rate side.
			   int bitTarget = allowedBits - closeEnough;

			   /// Initialisation is complete and the adapting bi-section/power model algorithm starts
			   /// here. The stopping criteria are 1) a rate less than, but close to, the allowed bits
			   /// or 2) small change in distortion when reducing the interval.
			   int done = 0;
			   while(!done)
			   {
				   int prevDmax = Dmax;

				   /// Make a prediction assuming a power law model.
	   //			Dmax = _codec->FitDistPowerModel(Rl, Dl, Ru, Du, bitTarget);
				   /// Only use this prediction if it is bounded by (Rl,Dl) and (Ru,Du).
	   //			if( (Dmax < Du)||(Dmax > Dl) )	///< Out of bound.
	   //				Dmax = _codec->FitDistLinearModel(Rl, Dl, Ru, Du, bitTarget);

				   /// Encourage the descent direction by adding a decreasing factor to the
				   /// predicted Dmax such that convergence to Dmax is from the (Rl,Dl) side.
	   //		  Dmax += abs(Dl - Dmax)/4;

	   //			if( (Dmax < Du)||(Dmax > Dl)||(Dmax == prevDmax) )	///< Still out of bound.
					   Dmax = ((Du + Dl) + 1) >> 1;	///< Set the midpoint max distortion.

				   /// At each macroblock reduce the quant value until the distortion is lower
				   /// than Dmax. pQ[] must always hold the lower rate (smaller valued) quant vector
				   /// as the previous best choice.
				   R = 0;
				   int firstMbChange = len;
				   if(invalidated)	///< Frame encoded coeffs must be invalidated if _pQ[] does not represent the actual QPs used.
					   firstMbChange = 0;
			 mbSkipRun = 0;
				   for(mb = 0; mb < len; mb++)
				   {
					   MacroBlockH264* pMb = &(_codec->_pMb[mb]);

					   /// Record the found QP where the macroblock dist is just below Dmax and accumulate the rate for this macroblock.
					   _pQ[mb] = _codec->GetMbQPBelowDmaxVer3(*pMb, _pQ[mb], Dmax, &firstMbChange, qEnd, FALSE);
					   R += pMb->_rate[_pQ[mb]]; ///< Rate = 0 for skipped mbs.
			   if(!pMb->_skip)
			   {
				 /// Sum of skip run and coded mb bits accumulated.
				 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
				 mbSkipRun = 0;
			   }//end if !_skip...
			   else
				 mbSkipRun++;

					   /// An accurate early exit strategy is not possible because the model prediction require two valid (Dmax,R) points
					   /// for the whole frame.

				   }//end for mb...
			 /// Add last skip run.
			 if(mbSkipRun)
			   R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);

				   /// Test the stopping criteria.
				   int rBndDiff = abs(Ru - Rl);			///< Optimal solution is rate bounded in a small enough range.
				   int dDiff = abs(prevDmax - Dmax);	///< Has not changed by much from the previous iteration (converged).
				   int rDiff = abs(bitTarget - R);		///< Close enough to the allowed bits.
				   if( (rBndDiff < (4*closeEnough)) ||
						   ( (rDiff < closeEnough)||((dDiff < closeEnoughDist))) ||
				 (iterations > _codec->_interIterations) )
				 {
					   /// The new point is the preferable point to choose but if the rate is not below allowedBits
					   /// then the (Rl,Dl) point is selected. Use the invalidated signal to indicate if the mbs
			   /// must be re-processed.
					   if(R > allowedBits)
					   {
						   /// Load the lower vector as it is always below the target rate.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   R = Rl;
				 invalidated = 1;
					   }//end if R...
			   else
				 invalidated = 0;

					   /// Optimal solution is found.
					   done = 1;
				   }//end if rDiff...
				   else
				   {
					   if(allowedBits > R)	///< Inner predicted point is now lower point.
					   {
						   Dl	= Dmax;
						   Rl	= R;
						   /// pQ[] is the lower vector.
						   memcpy((void *)_pQl, (const void *)_pQ, len * sizeof(int));
						   invalidated = 0;
					   }//end if allowedBits...
					   else							///< Inner predicted point is now upper point.
					   {
						   Du	= Dmax;
						   Ru	= R;
						   /// pQ[] must be reset to lower vector to maintain a descent convergence.
						   memcpy((void *)_pQ, (const void *)_pQl, len * sizeof(int));
						   invalidated = 1;	///< pQ[] now does not represented the state of the last encoded frame.
					   }//end else...

				   }//end else...

				   iterations++;
			   }//end while !done...

			   /// Set the macroblock QP values to their found states.
		   if(invalidated)
		   {
				 for(mb = 0; mb < len; mb++)
				 {
					 _codec->_pMb[mb]._mbQP    = _pQ[mb];
					 _codec->_pMb[mb]._mbEncQP = _pQ[mb];
				 }//end for mb...
		   }//end if invalidated...

		 }//end if Rl...
		 */
		 ///======================================================================================
		 /*
		 /// Simple Truncation Algorithm

			 /// If QP = H264V2_MAX_QP and still does not fit then a truncation process is nessecary. The truncation
			 /// is somewhere between every mb encoded with motion with zero'ed coeffs and some mbs with max QP. The
		 /// _rate[0] member of the mbs holds the min encoding and is zero for skipped. Proceed by encoding each
		 /// skip run and max QP pair per mb and then count the bits to the end.
			 R         = 0;	///< Reset.
		 mbSkipRun = 0;
			 for(mb = 0; mb < len; mb++)
			 {
		   MacroBlockH264* pMb = &(_codec->_pMb[mb]);  ///< Simplify mb addressing.

		   /// Do mb encoding including motion and max QP.
			   pMb->_mbQP = H264V2_MAX_QP;
			   R += _codec->ProcessInterMbImplStd(pMb, 0, 1);  ///< Returns 0 if skipped.
		   if(!pMb->_skip)
		   {
			 /// Sum of skip run and coded mb bits accumulated.
			 R += _codec->_pHeaderUnsignedVlcEnc->Encode(mbSkipRun);
			 mbSkipRun = 0;

			 /// Add up min encodings from the next mb to the end.
			 int bitsToEnd = 0;
			 int run       = 0;
			 int mbi       = mb + 1;
			 while(mbi < len)
			 {
			   MacroBlockH264* pMbi = &(_codec->_pMb[mbi]);
			   int r = pMbi->_rate[0];
			   if(r) ///< Not skipped.
			   {
				 bitsToEnd += (r + _codec->_pHeaderUnsignedVlcEnc->Encode(run));
				 run = 0;
			   }//end if r...
			   else
				 run++;
			   mbi++;
			 }//end while mbi...
			 if(run)
				bitsToEnd += _codec->_pHeaderUnsignedVlcEnc->Encode(run);

			 /// With this mb max QP encoded and min encoding for all remaining mbs to the end,
			 /// if it does not fit then mark it as the min encoding point and break.
			 if((R + bitsToEnd) >= allowedBits)
			 {
					   minMBIndex = mb;
					   break;
			 }//end if R...
		   }//end if !_skip...
		   else
			 mbSkipRun++;

			 }//end for mb...
		 */
}//end DamageControl.

/** Encode the image data for Inter pictures with a Dmax criterion.
Process all macroblocks in order with a mb Dmax limit and only write the result
to the ref image space if the writeRef code is set. Bit 1 of writeRef refers to
motion compensation and bit 0 to adding the difference to the ref. The motion
estimation process with its associated data structures is assumed to have been
completed before this method is called. The macroblock obj is prepared for
coding onto the bit stream.
Note: For iteratively calling this method;
	Call 1:			writeRef = 2 (compensation to ref but no adding).
	Call 2 - X: writeRef = 0 (ref is motion compensated already from call 1).
	Call final:	writeRef = 1 (allow final add to ref).
@param allowedBits	: Total remaining bits to target.
@param bitsUsed			: Num of bits used for this encoding.
@param writeRef			: Bit code 1x/0x = do/do not comp. x1/x0 do/do not add ref.
@return							: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneEncoderImplDMax::Encode(int allowedBits, int* bitsUsed, int writeRef)
{
	/// Whip through each macroblock and encode. The stream writing of
	/// the macroblock is seperate to allow further rate-distortion decision 
	/// making later on in the encoding process.
	int compRef = writeRef & 2;
	int addRef = writeRef & 1;
	int len = _codec->_mbLength;
	int dmax = _codec->_dMax;
	/// Set a bound on the max quality by choosing a min qp value that the MinMax search is limited to.
	int qEnd = _codec->_minQPInter;
	int coeffBits = 0;

	/// Slice without partitioning and therefore only one set of slice parameters.

	/// Set up the input and ref image mem overlays.
	_codec->_Lum->SetOverlayDim(4, 4);
	_codec->_Cb->SetOverlayDim(4, 4);
	_codec->_Cr->SetOverlayDim(4, 4);
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// All integer transforms are Inter in this method.
	_codec->_pF4x4TLum->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TLum->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	_codec->_pF4x4TChr->SetMode(IForwardTransform::TransformOnly);
	_codec->_pF4x4TChr->SetParameter(IForwardTransform::INTRA_FLAG_ID, 0);
	/// By default the DC transforms were set in the TransformOnly mode in the Open() method.

	/// Motion estimation has been previously performed outside of this method and therefore
	/// only motion compensation is required here. Prepare for motion compensation on a per 
	/// macoblock basis. The vectors themselves are held in _pMotionEstimationResult.
	if (compRef)
		_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Get the motion vector list to work with. Assume SIMPLE2D type list as only a
	/// single 16x16 motion vector is considered per macroblock in this implementation
	/// i.e. Inter_16x16 mode only
	int	listLen = _codec->_pMotionEstimationResult->GetLength();
	if (listLen != len)
	{
		*bitsUsed = 0;
		return(0);	///< Error: Motion vector list must match.
	}//end if listLen...

  ///---------------------- Macroblock Process ------------------------------------------
	/// Rip through each macroblock as a linear array and process the
	/// motion vector and each block within the macroblock.
	for (int mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);

		///------------------- Motion compensation ------------------------------------------------
		pMb->_mbPartPredMode = MacroBlockH264::Inter_16x16;	///< Fixed at 16x16 for now.

		/// Get the 16x16 motion vector from the motion estimation result list and apply
		/// it to the macroblock. The reference image will then hold the compensated macroblock
		/// to be used as the prediction for calcualting the residual.
		int mvx = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 0);
		int mvy = _codec->_pMotionEstimationResult->GetSimpleElement(mb, 1);
		if (compRef)
		{
			_codec->_pMotionCompensator->Compensate(pMb->_offLumX, pMb->_offLumY, mvx, mvy);
		}//end if compRef...

			/// Store the vector for this macroblock.
		pMb->_mvX[MacroBlockH264::_16x16] = mvx;
		pMb->_mvY[MacroBlockH264::_16x16] = mvy;

		/// Get the predicted motion vector for this mb as the median of the neighbourhood 
		/// vectors and subtract it from the mb vector.
		int predX, predY;
		MacroBlockH264::GetMbMotionMedianPred(pMb, &predX, &predY);
		pMb->_mvdX[MacroBlockH264::_16x16] = mvx - predX;
		pMb->_mvdY[MacroBlockH264::_16x16] = mvy - predY;

		///------------------- Macroblock processing ----------------------------------------------
	  /// Note that the 1st mb will have a delta offset from _slice._qp to get it to _mbQP = H264V2_MAX_QP.
		pMb->_mbQP = H264V2_MAX_QP;

		/// For desperate measures when the previous encoding failed to reach the targetted rate then 
		/// a further quantisation process can be implemented here where the coeffs will be zeroed. This
		/// has been tested but is not implemented because the effectiveness is limited.
		if (_codec->_pRateCntlPFrames != NULL)
		{
			if (_codec->_pRateCntlPFrames->OutOfBounds() && _codec->_pRateCntlPFrames->LowerDistortionOverflow())
				pMb->_mbQP = H264V2_MAX_QP + 16;
		}//end if _pRateCntlPFrames...

			/// Include all macroblocks.
		pMb->_include = 1;
		/// Find QP where the mb Lum dist is just below Dmax for this mb. Count the bits for the coeffs only.
		if (_codec->_modeOfOperation == H264V2_MB_QP_AVG_ADAPTIVE)
			coeffBits += _codec->ProcessInterMbImplStd(pMb, addRef, 3, dmax, qEnd);
		else
			_codec->ProcessInterMbImplStd(pMb, addRef, 2, dmax, qEnd);

	}//end for mb...

  /// Store the coeff bits per pel.
	_codec->_coeffBitsPerPel = (double)coeffBits / (double)(_codec->_lumWidth*_codec->_lumHeight);

	*bitsUsed = 0;
	return(1);
}//end InterImgPlaneEncoderImplDMax::Encode.

/** Decode the Inter macroblocks to the reference img.
The macroblock obj encodings must be fully defined before calling
this method.
@return	: 1 = success, 0 = error.
*/
int H264v2Codec::InterImgPlaneDecoderImplStdVer1::Decode(void)
{
	int mb;
	int len = _codec->_mbLength;

	/// Set up the input and ref image mem overlays.
	_codec->_RefLum->SetOverlayDim(4, 4);
	_codec->_RefCb->SetOverlayDim(4, 4);
	_codec->_RefCr->SetOverlayDim(4, 4);
	_codec->_16x16->SetOverlayDim(16, 16);
	_codec->_8x8_0->SetOverlayDim(8, 8);
	_codec->_8x8_1->SetOverlayDim(8, 8);

	/// Prepare for motion compensation on a per macoblock basis.
	_codec->_pMotionCompensator->PrepareForSingleVectorMode();

	/// Whip through each macroblock. Decode the extracted encodings. All modes
	/// and parameters have been extracted by the ReadMacroBlockLayer() method.
	for (mb = 0; mb < len; mb++)
	{
		/// Simplify the referencing to the current macroblock.
		MacroBlockH264* pMb = &(_codec->_pMb[mb]);
		int lOffX = pMb->_offLumX;
		int lOffY = pMb->_offLumY;
		int cOffX = pMb->_offChrX;
		int cOffY = pMb->_offChrY;

		///------------------- Motion compensation -----------------------------------------------------------
		if (pMb->_mbPartPredMode != MacroBlockH264::Inter_16x16)	///< Fixed at 16x16 mode for now.
		{
			_codec->_errorStr = "[H264V2::InterImgPlaneDecoderImplStdVer1::Decode] Only supports Inter_16x16 mode";
			return(0);
		}//end if !Inter_16x16...

		/// Compensate the vector and hope the encoder estimator ensured that
		/// all pels fall inside the image space. The motion vector was decoded
		/// from the vector differences in the ReadMacroBlockLayer() method.
		_codec->_pMotionCompensator->Compensate(lOffX, lOffY, pMb->_mvX[MacroBlockH264::_16x16], pMb->_mvY[MacroBlockH264::_16x16]);

		if (pMb->_coded_blk_pattern)
		{
			/// --------------------- Inverse Transform & Quantisation -------------------------------
			if (pMb->_mbPartPredMode == MacroBlockH264::Inter_16x16)
				_codec->InverseTransAndQuantInter16x16MBlk(pMb, 0);

			/// --------------------- Image Storing into Ref -----------------------------------------
			/// Fill the image (difference) colour components from all the non-DC 4x4 
			/// blks (i.e. Not blks = -1, 17, 18) of the macroblock temp blocks. 
			MacroBlockH264::StoreBlks(pMb, _codec->_16x16, 0, 0, _codec->_8x8_0, _codec->_8x8_1, 0, 0, 0);

			/// --------------------- Add the prediction ---------------------------------------------
			/// Lum.
			_codec->_RefLum->SetOverlayDim(16, 16);
			_codec->_RefLum->SetOrigin(lOffX, lOffY); ///< Align the Ref Lum img block with this macroblock.
			_codec->_16x16->SetOverlayDim(16, 16);
			_codec->_16x16->SetOrigin(0, 0);
			_codec->_RefLum->AddWithClip255(*(_codec->_16x16));	///< Add to ref Lum and leave result in ref img.
			/// Cb.
			_codec->_RefCb->SetOverlayDim(8, 8);
			_codec->_RefCb->SetOrigin(cOffX, cOffY);
			_codec->_8x8_0->SetOverlayDim(8, 8);
			_codec->_8x8_0->SetOrigin(0, 0);
			_codec->_RefCb->AddWithClip255(*(_codec->_8x8_0));
			/// Cr.
			_codec->_RefCr->SetOverlayDim(8, 8);
			_codec->_RefCr->SetOrigin(cOffX, cOffY);
			_codec->_8x8_1->SetOverlayDim(8, 8);
			_codec->_8x8_1->SetOrigin(0, 0);
			_codec->_RefCr->AddWithClip255(*(_codec->_8x8_1));

		}//end if _coded_blk_pattern...

	}//end for mb...

	return(1);
}//end InterImgPlaneDecoderImplStdVer1::Decode.

/*
-------------------------------------------------------------------------------------------
	Private helper methods for prediction tools.
-------------------------------------------------------------------------------------------
*/

/** Calc the median of 3 numbers.
@param x	:	1st num.
@param y	:	2nd num.
@param z	:	3rd num.
@return		: The median of x, y and z.
*/
int H264v2Codec::Median(int x, int y, int z)
{
	int min, max;

	// min = MIN(x,MIN(y,z)) and max = MAX(x,MAX(y,z)).
	if ((y - z) < 0) { min = y;	max = z; }
	else { min = z; max = y; }
	if (x < min) min = x;
	if (x > max) max = x;
	// Median.
	int result = x + y + z - min - max;

	return(result);
}//end Median.

void H264v2Codec::DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title)
{
	int i, j;

	MeasurementTable* pT = new MeasurementTable();

	int cols = pBlk->GetWidth();
	int rows = pBlk->GetHeight();

	pT->Create(cols, rows);
	for (j = 0; j < cols; j++)
	{
		pT->SetHeading(j, "");
		pT->SetDataType(j, MeasurementTable::INT);
	}//end for j...

	pT->SetTitle(title);
	for (i = 0; i < rows; i++)
		for (j = 0; j < cols; j++)
			pT->WriteItem(j, i, pBlk->Read(j, i));

	pT->Save(filename, ",", 1);

	delete pT;
}//end DumpBlock.
========== END FILE: H264v2Codec/old/H264v2Codec.cpp ==========

========== BEGIN FILE: H264v2Codec/old/H264v2Codec.h ==========
Bundle entry: 152
Original bytes: 31689
Original SHA-256: 6f1c5296486f240874d5d9c0ea3dcba8eb85cb52fa3c70c1fe1d88e8dac3968d
Decoded as: utf-8
---------- SOURCE TEXT ----------
/** @file

MODULE				: H264v2Codec

TAG						: H264V2C

FILE NAME			: H264v2Codec.h

DESCRIPTION		: A 2nd generation of video codecs based on the H.264 standard
								implementation. The primary interface is ICodecv2 for access 
								and configuration.

COPYRIGHT			: (c)CSIR 2007-2017 all rights resevered

LICENSE				: Software License Agreement (BSD License)

RESTRICTIONS	: Redistribution and use in source and binary forms, with or without 
								modification, are permitted provided that the following conditions 
								are met:

								* Redistributions of source code must retain the above copyright notice, 
								this list of conditions and the following disclaimer.
								* Redistributions in binary form must reproduce the above copyright notice, 
								this list of conditions and the following disclaimer in the documentation 
								and/or other materials provided with the distribution.
								* Neither the name of the CSIR nor the names of its contributors may be used 
								to endorse or promote products derived from this software without specific 
								prior written permission.

								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
								"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
								LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
								A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
								CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
								EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
								PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
								PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
								LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
								NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
								SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===========================================================================
*/
#ifndef _H264V2CODEC_H
#define _H264V2CODEC_H

#pragma once
#include <cstddef>
#include "ICodecv2.h"
#include "ICodecInnerAccess.h"

#include "BlockH264.h"
#include "NalHeaderH264.h"
#include "SliceHeaderH264.h"
#include "SeqParamSetH264.h"
#include "PicParamSetH264.h"

#ifdef _WIN32
//#include "Windows.h"

//#define H264V2C_MICROSOFT_PARALLEL 1
#ifdef H264V2C_MICROSOFT_PARALLEL
  #include <ppl.h>
  #include <ppltasks.h>
  using namespace concurrency;
  using namespace std;
#endif
#endif

#ifdef H264V2_DUMP
/// For storing measurements during testing.
//#define H264V2_DUMP_HEADERS 1
//#define H264V2_DUMP_MB_RD_DATA 1
//#define H264V2_DUMP_TIMING 1
//#define H264V2_DUMP_FRM_RD_DATA 1
#include "MeasurementTable.h"
#endif

/// Dump filenames
#define H264V2_RATE_CNTL_PFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlPFrames.csv"
#define H264V2_RATE_CNTL_IFRAMES "c:/keithf/Excel/VideoEvaluation/RateControlIFrames.csv"

// forward declarations
class RGBtoYUV420Converter;
class YUV420toRGBConverter;
class IBitStreamWriter;
class IBitStreamReader;
class OverlayMem2Dv2;
class IForwardTransform;
class IInverseTransform;
class VectorStructList;
class IMotionEstimator;
class IMotionCompensator;
class IMotionVectorPredictor;
class IVlcEncoder;
class IVlcDecoder;
class MacroBlockH264;
class H264MbImgCache;
class IRateControl;

class ConvYUV420_16toBGR24;
class RGBtoYUV420Converter16;

/*
===========================================================================
  Codec specific definitions.
===========================================================================
*/

/// Defined Modes of Operation for bit allocation stratergies - "mode of operation".
#define	H264V2_OPEN						        0	/// (Default) Slice QP defines the bit usage without control.
#define H264V2_MB_QP_MINMAX_ADAPTIVE	1	/// Macroblock QP is adapted to meet the frame bit target.
#define H264V2_MB_QP_AVG_ADAPTIVE	    2	/// Macroblock QP is adapted to meet an average bit target.
#define H264V2_MB_QP_DMAX_ADAPTIVE	  3	/// Macroblock QP is adapted to meet Dmax target.

/// For mode of operation = H264V2_MB_QP_AVG_ADAPTIVE the following rate control model types may be set:
#define H264V2_RATE_CONTROL_MODEL_QUAD  0	/// Inverse quadratic model.
#define H264V2_RATE_CONTROL_MODEL_POW   1	/// Power model.
#define H264V2_RATE_CONTROL_MODEL_LOG   2	/// Inverse log model.
//#define H264V2_RATE_CONTROL_MODEL_MULTI 3	/// Combination model.

/// Seq and Pic param max encoded length.
#define	H264V2_ENC_PARAM_LEN            32

/// Use non-reversible CCIR-601 colour conversions.
//#define _CCIR601

/*
===========================================================================
  Class definition.
===========================================================================
*/
class H264v2Codec : public ICodecv2, public ICodecInnerAccess
{
  /// construction
public:
  H264v2Codec();
  virtual ~H264v2Codec();

  /// ICodecv2 Interface Implementation
public:

  int		GetParameter(const char* type, int* length, void* value);
  void	GetParameterName(int ordinal, const char** name, int* length);
  int		SetParameter(const char* type, const char* value);

  char* GetErrorStr(void) { return((char *)_errorStr); }
  int		Ready(void) { return(_codecIsOpen); }
  int		GetCompressedBitLength(void) { return((int)_bitStreamSize); }
  int		GetCompressedByteLength(void)
  {
    int x = (int)_bitStreamSize / 8; if (_bitStreamSize & 0x7) x++; return(x);
  }
  void* GetReference(int refNum) { return((void*)_pRLum); }

  void	Restart(void);
  int		Open(void);
  int		Close(void);
  int		Code(void* pSrc, void* pCmp, int codeParameter);
  int		Decode(void* pCmp, int bitLength, void* pDst);

  /// ICodecInnerAccess Interface Implementation
public:
  void* GetMember(const char* type, int* length);
  void	GetMemberName(int ordinal, const char** name, int* length);
  int		SetMember(const char* type, void* pValue);

  /// Codec parameters.
private:
  /// Unique Codec identification.
  int		_idCode;																				///"codecid"
  /// The codec parameters are seperated into 2 categories. Those that are static throughout the
  /// life span of an Open()/Close() session and those that are dynamic and can be changed per
  /// picture Code()/Decode(). 

  /// -------------- Static Parameters ------------------------------------------------------ 
  /// Set before Open() and cleared at Close().

  /// Description of the source/destination image.
  int		_width;																					///< "width"
  int		_height;																				///< "height"
  int		_inColour;																			///< "incolour"
  int		_outColour;																			///< "outcolour"
  bool  _flip;                                          ///< "flip" Stores whether the internal color converters should flip the image during conversion.

  /// Modes of operation (bit allocation strategies).
  int		_modeOfOperation;																///< "mode of operation"
  int   _intraIterations;                               ///< "intra iteration limit"
  int   _interIterations;                               ///< "inter iteration limit"
  int   _timeLimitMs;                                   ///< "time limit msec"
  int   _rateControlModelType;                          ///< "rate control model type"  (Only valid for mode of operation = 2)

  /// Parameter set handling.
  int		_currSeqParam;																	///< "seq param set"
  int		_currPicParam;																	///< "pic param set"
  int		_genParamSetOnOpen;															///< "generate param set on open"
  int   _prependParamSetsToIPic;                        ///< "prepend param sets to i-pictures"

  int		_startCodeEmulationPrevention;									///< "start code emulation prevention"

  /// -------------- Dynamic Parameters ------------------------------------------------------ 
  /// Set before Code()/Decode(). Remain in effect until modified.

  /// Picture properties.
  int		_pictureCodingType;															///< "picture coding type"	(Will be interpreted into/from NAL type)
  int		_lastPicCodingType;															///< "last pic coding type"
  int		_pQuant;																				///< "quality"
  int   _minQPIntra;                                    ///< "minimum intra qp"
  int   _minQPInter;                                    ///< "minimum inter qp"

  /// I-Picture modifiers.
  int		_autoIPicture;																	///< "autoipicture"
  int		_iPictureMultiplier;														///< "ipicturemultiplier"
  int		_iPictureFraction;															///< "ipicturefraction"
  int		_iPictureDMaxMultiplier;												///< "ipicture dmax multiplier"
  int		_iPictureDMaxFraction;													///< "ipicture dmax fraction"

  int  _seqParamSetLog2MaxFrameNumMinus4;               ///< "seq param log2 max frame num minus 4"

  int  _dMax;                                           ///< "max distortion"
  int  _maxBitsPerFrame;                                ///< "max bits per frame"
  int  _numRateCntlFrames;                              ///< "num rate control frames"
  int  _rateOvershootPercent;                           ///< "rate overshoot percent"

  int _enableROIEncoding;                               ///< "enable roi encoding"

/// Attributes
private:
  /// Intermediate input/output YCbCr image mem members.
  int							_lumWidth;		/// pix width.
  int							_lumHeight;		/// pix height.
  short*					_pLum;				/// Space to compress from and decompress to.
  int							_chrWidth;
  int							_chrHeight;
  short*					_pChrU;
  short*					_pChrV;

  /// 2-D overlays for YCbCr picture mem.
  OverlayMem2Dv2*	_Lum;
  OverlayMem2Dv2*	_Cb;
  OverlayMem2Dv2*	_Cr;

  /// Reference image mem members.
  short*					_pRLum;
  short*					_pRChrU;
  short*					_pRChrV;

  /// 2-D overlays for YCbCr picture reference mem.
  OverlayMem2Dv2*	_RefLum;
  OverlayMem2Dv2*	_RefCb;
  OverlayMem2Dv2*	_RefCr;

  /// Temp 16x16 and 8x8 mem blocks for use during macroblock prediction.
  short*					_p16x16;
  OverlayMem2Dv2*	_16x16;
  short*					_p8x8_0;
  OverlayMem2Dv2*	_8x8_0;
  short*					_p8x8_1;
  OverlayMem2Dv2*	_8x8_1;

  /// Temp 4x4 blks for distortion calculations during transform and quant processes.
  BlockH264       _tmpBlk[4][4];

  /// Image caching.
  H264MbImgCache* _mbImg;

private:
  void				ResetMembers(void);
  int					CodeNonPicNALTypes(void* pCmp, int frameBitLimit);

  int					SetSeqParamSet(int index);
  int					WriteSeqParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int         WriteSeqParamScalingList(IBitStreamWriter* bsw, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					ReadSeqParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int         ReadSeqParamVuiParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamVuiHrdParams(IBitStreamReader* bsr); ///< Currently this method is a dummy read.
  int         ReadSeqParamScalingList(IBitStreamReader* bsr, int* scalingList, int length, int* useDefaultScalingMatrix); ///< Untested.
  int					SetPicParamSet(int index, int seqRef);
  int					WritePicParamSet(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed, int index);
  int					ReadPicParamSet(IBitStreamReader* bsr, int remainingBits, int* bitsUsed, int* idx, int* changedFlag);
  int					GetCodecParams(int picParamSet);

  int					WriteNALHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadNALHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);
  int					WriteSliceLayerHeader(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceLayerHeader(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteTrailingBits(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadTrailingBits(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int         InsertEmulationPrevention(IBitStreamWriter* bsw, int startOffset);
  int         RemoveEmulationPrevention(IBitStreamReader* bsr);

  int					WriteSliceDataLayer(IBitStreamWriter* bsw, int allowedBits, int* bitsUsed);
  int					ReadSliceDataLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  int					WriteMacroBlockLayer(IBitStreamWriter* bsw, MacroBlockH264* pMb, int allowedBits, int* bitsUsed);
  int					MacroBlockLayerBitCounter(MacroBlockH264* pMb);
  int					MacroBlockLayerCoeffBitCounter(MacroBlockH264* pMb);
  int					ReadMacroBlockLayer(IBitStreamReader* bsr, int remainingBits, int* bitsUsed);

  void				ApplyLoopFilter(void);
  void				VerticalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);
  void				HorizontalFilter(MacroBlockH264* pMb, short** img, int lumFlag, int rowOff, int colOff, int iter, int boundaryStrength);

  void				TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  int         GetQPtoNonZeroCoeff(MacroBlockH264* pMb, int minQP);
  int         TransAndQuantIntra16x16MBlkWithInv(MacroBlockH264* pMb, int withD);

  void				TransAndQuantIntra16x16ModeBlk(IForwardTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);
  void				InverseTransAndQuantIntra16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);
  void				InvTransAndQuantIntra16x16ModeBlk(IInverseTransform* pTQ, BlockH264* pBlk, short* pDcBlkCoeff);

  void				TransAndQuantInter16x16MBlk(MacroBlockH264* pMb);
  int         TransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int Dmax, int minQP);
  void				InverseTransAndQuantInter16x16MBlk(MacroBlockH264* pMb, int tmpBlkFlag);

  int					GetIntra16x16LumPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* in, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPred(MacroBlockH264* pMb, OverlayMem2Dv2* ref, OverlayMem2Dv2* pred, int predMode);
  void				GetIntra16x16LumDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntra16x16LumPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* lum, OverlayMem2Dv2* pred);
  int					GetIntraVertPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  int					GetIntraHorizPred(MacroBlockH264* pMb, OverlayMem2Dv2* img, OverlayMem2Dv2* pred, int lumFlag);
  void				GetIntra8x8ChrDCPred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPlanePred(MacroBlockH264* pMb, OverlayMem2Dv2* chr, OverlayMem2Dv2* pred);
  int					GetIntra8x8ChrPredAndMode(MacroBlockH264* pMb, OverlayMem2Dv2* cb, OverlayMem2Dv2* cr,
                                        OverlayMem2Dv2* refCb, OverlayMem2Dv2* refCr, OverlayMem2Dv2* predCb, OverlayMem2Dv2* predCr);

  int					Median(int x, int y, int z);
  static void DumpBlock(OverlayMem2Dv2* pBlk, char* filename, const char* title);

  /// The implementations of img plane encoders and decoders is done through a common
  /// interface and as private nested classes.
private:
  /// Common interface for img plane encoders and decoders as nested classes.
  class IImagePlaneEncoder
  {
  public:
    virtual ~IImagePlaneEncoder(void) { }
    virtual int Encode(int allowedBits, int* bitsUsed, int writeRef) = 0;
    virtual int Create(int length) { return(1); }
  };//end class IImagePlaneEncoder.
  friend class IImagePlaneEncoder;

  class IImagePlaneDecoder
  {
  public:
    virtual ~IImagePlaneDecoder(void) { }
    virtual int Decode(void) = 0;
  };//end class IImagePlaneDecoder.
  friend class IImagePlaneDecoder;

  /// Implementations of img plane encoders and decoders as nested classes of codec.

  /// Image Plane Encoders.

  class IntraImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// I-frame IDR baseline encoder.
  {
  public:
    IntraImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplStdVer1.
  friend class IntraImgPlaneEncoderImplStdVer1;

  class IntraImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< I-frame macroblock level Quant adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. 
  public:
    IntraImgPlaneEncoderImplMinMax(H264v2Codec* codec) { _codec = codec; _pQ = NULL; _pQl = NULL; _pMbList = NULL; }
    virtual ~IntraImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[3 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pMbList = _pQl + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pMbList;
  };//end class IntraImgPlaneEncoderImplMinMax.
  friend class IntraImgPlaneEncoderImplMinMax;

  class IntraImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    IntraImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneEncoderImplDMax.
  friend class IntraImgPlaneEncoderImplDMax;

  class InterImgPlaneEncoderImplStdVer1 : public IImagePlaneEncoder	/// P-frame baseline encoder.
  {
  public:
    InterImgPlaneEncoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplStdVer1(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplStdVer1.
  friend class InterImgPlaneEncoderImplStdVer1;

  class InterImgPlaneEncoderImplMinMax : public IImagePlaneEncoder	///< P-frame macroblock PQ adaptive encoder.
  {
    /// MinMax algorithm with rate constraint. Uses bisection method to find optimal selection.
  public:
    InterImgPlaneEncoderImplMinMax(H264v2Codec* codec)
    {
      _codec = codec; _pQ = NULL; _pQl = NULL; _pDistortionDiff = NULL; _pMbList = NULL; _pLastMbCoded = NULL; _pLastMbQP = NULL;
    }
    virtual ~InterImgPlaneEncoderImplMinMax(void) { if (_pQ != NULL) delete[] _pQ; _pQ = NULL; }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
    int DamageControlMvOnly(int allowedBits, int* bitsUsed);
    int DamageControl(int allowedBits, int currBitCost);
    int Create(int length)
    {
      if (_pQ != NULL) delete[] _pQ; _pQ = NULL;
      _pQ = new int[6 * length]; if (_pQ == NULL) return(0);
      _pQl = _pQ + length; _pDistortionDiff = _pQl + length; _pMbList = _pDistortionDiff + length;
      _pLastMbCoded = _pMbList + length; _pLastMbQP = _pLastMbCoded + length; return(1);
    }
  private:
    H264v2Codec* _codec;
    int*	_pQ;
    int*	_pQl;
    int*  _pDistortionDiff;
    int*  _pMbList;
    int*  _pLastMbCoded;  ///< Audit trail.
    int*  _pLastMbQP;
  };//end class InterImgPlaneEncoderImplMinMax.
  friend class InterImgPlaneEncoderImplMinMax;

  class InterImgPlaneEncoderImplDMax : public IImagePlaneEncoder	/// I-frame mb level QP adaptive to a target Dmax encoder.
  {
  public:
    InterImgPlaneEncoderImplDMax(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneEncoderImplDMax(void) { }
    int Encode(int allowedBits, int* bitsUsed, int writeRef);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneEncoderImplDMax.
  friend class InterImgPlaneEncoderImplDMax;

  /// Image Plane Decoders.

  class IntraImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// I-frame IDR baseline decoder.
  {
  public:
    IntraImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~IntraImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class IntraImgPlaneDecoderImplStdVer1.
  friend class IntraImgPlaneDecoderImplStdVer1;

  class InterImgPlaneDecoderImplStdVer1 : public IImagePlaneDecoder	/// P-frame baseline decoder.
  {
  public:
    InterImgPlaneDecoderImplStdVer1(H264v2Codec* codec) { _codec = codec; }
    virtual ~InterImgPlaneDecoderImplStdVer1(void) { }
    int Decode(void);
  private:
    H264v2Codec* _codec;
  };//end class InterImgPlaneDecoderImplStdVer1.
  friend class InterImgPlaneDecoderImplStdVer1;

  /// Code refactoring methods.
  int   FitDistPowerModel(int rl, int dl, int ru, int du, int r);
  int   FitDistLinearModel(int rl, int dl, int ru, int du, int r);

  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred);
  int   ProcessIntraMbImplStd(MacroBlockH264* pMb, int withDR, int usePrevPred, int Dmax, int minQP);
  void  CoeffZeroingQuantisation(MacroBlockH264* pMb);
  void  CoeffZeroingQuantisationVer2(MacroBlockH264* pMb);
  int   ProcessIntraMbImplStdMin(MacroBlockH264* pMb);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR);
  int   ProcessInterMbImplStd(MacroBlockH264* pMb, int addRef, int withDR, int Dmax, int minQP);
  int   ProcessInterMbImplStdMin(MacroBlockH264* pMb);
  int   GetDeltaQP(MacroBlockH264* pMb);
  int   GetMbQPBelowDmax(MacroBlockH264 &mb, int atQP, int Dmax, int decQP, int* changeMb, int lowestQP, bool intra);
  int   GetMbQPBelowDmaxVer2(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxVer3(MacroBlockH264 &mb, int atQ, int Dmax, int* changeMb, int lowestQ, bool intra);
  int   GetMbQPBelowDmaxApprox(MacroBlockH264 &mb, int atQP, int Dmax, int epsilon, int decQP, int* changeMb, int lowestQP, bool intra);

  /// In-line methods. 

  /** Get the previous macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Previous Mb QP.
  */
  inline int GetPrevMbQP(MacroBlockH264* pMb);

  /** Get the next macroblock QP value.
  Picture and slice boundaries are considered in returning the
  neighbouring mb QP value.
  @param pMb    : Macroblock to operate on.
  @return       : Next Mb QP.
  */
  inline int GetNextMbQP(MacroBlockH264* pMb);

  /** Get the ROI modified distortion value.
  The input distortion is modified and returned to reflect the region
  of interest bias.
  @param pMb    : Macroblock to operate on.
  @return       : Modified distortion.
  */
  inline int ROIDistortion(int mbIndex, int d)
  { if (_enableROIEncoding) return( (int)(0.5 + ((double)d * _roiMultiplier[mbIndex])) ); else return(d); }

  /** Run a high performance timer
  @return : A timer exists.
  */
  static double _cpuFreq;
  int _startTime;
  inline static int SetCounter(void) 
  {
#ifdef _WIN32
    _cpuFreq = 0.0;
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
	    return(0);
    _cpuFreq = double(li.QuadPart)/1000.0;  ///< In ms
    return(1);
#else
    return 0;
#endif
  }//end SetCounter.

  inline static double GetCounter(void)
  {
#ifdef _WIN32
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    if(_cpuFreq != 0)
      return( double(li.QuadPart)/_cpuFreq );
    else
      return(0.0);
#else
    return 0.0;
#endif
  }//end GetCounter.

/// Codec Status.
private:
	char*		_errorStr;
  char    _errorInfo[256];
	int			_codecIsOpen;
	int			_bitStreamSize;

/// Constants.
private:
	/// The id must be unique for every codec implementation.
	static const unsigned short H264V2_ID = 1003;

	/// List of all parameter names accessed via GetParameterName().
	static const int		PARAMETER_LEN;		///< "parameters".
	static const char*	PARAMETER_LIST[];	///< ...of PARAMETER_LEN.

	/// List of all member names accessed via GetMemberName().
	static const int		MEMBER_LEN;			///< "members".
	static const char*	MEMBER_LIST[];	///< ...of MEMBER_LEN.

	/// Scaling matrix for DC coeffs. Unknown reason.
	static const int dc4x4Scale[];
	static const int dc2x2Scale[];

	/// Test sampling point coordinates for Intra_16x16 and Intra_8x8 prediction mode selection.
	static const int test16X[];
	static const int test16Y[];
	static const int test16Limit[];
	static const int testZoom16X[];
	static const int testZoom16Y[];
	static const int testZoom16Len;
  static const int delta16[][2];
	static const int testZoom8[][2];
  static const int testZoom8Len;
	static const int test8X[];
	static const int test8Y[];
	static const int test8Limit[];

	static const int testPntPath16xy[][2];
	static const int testPntPath8xy[][2];

	/// Loop filter constants.
	static const int alpha[52]; 
	static const int beta[52];
	static const int indexAbS[3][52];

	/// Fast search on the macroblock distortion vs. QP curve 
	/// changes the step size.
	static const int MbStepSize[];
  static const int NextQPDec[];

  /// Motion lambda constants for TCP-like adaptation.
  static const double MVLAMBDA_MAX;
  static const double MVLAMBDA_STEP;
  static const double MVLAMBDA_MULT;
  static const double MVLAMBDA_STEADYSTATE;

/// Operational members.
private:
	/// Compressed data stream access members.
	IBitStreamWriter*			_pBitStreamWriter;
	IBitStreamReader*			_pBitStreamReader;

	/// An input colour converter.
        RGBtoYUV420Converter16 *_pInColourConverter;
	ConvYUV420_16toBGR24 *_pOutColourConverter;	

	/// 4x4 and 2x2 IT DC and AC transform filters.
	IForwardTransform* _pF4x4TLum;
	IForwardTransform* _pF4x4TChr;
	IForwardTransform* _pFDC4x4T;
	IForwardTransform* _pFDC2x2T;
	IInverseTransform* _pI4x4TLum;
	IInverseTransform* _pI4x4TChr;
	IInverseTransform* _pIDC4x4T;
	IInverseTransform* _pIDC2x2T;

	/// The motion estimator distortion is tested to	determine if an
	/// I-frame would be more appropriate for the frame. But for abs
	/// diff algorithms a different linear factor is required compared
	/// to squared error algorithms.
	int										_motionFactor;						///< Sqr Err = 4, Abs diff = 2.
	/// Auto I-frame detection test variable to hold the previous picture distortion.
	long									_prevMotionDistortion;
	///	Auto I-frame flags to indicate which macroblocks must be excluded
	/// from the decision during the motion estimation process.
	bool*									_autoIFrameIncluded;

	IMotionEstimator*			  _pMotionEstimator;				///< Selected estimator dependent on mode.
	VectorStructList*			  _pMotionEstimationResult;	///< Motion vector list generated by estimator.
	IMotionCompensator*		  _pMotionCompensator;			///< Selected compensator dependent on mode.
	VectorStructList*			  _pMotionVectors;					///< Motion vector list input to compensators.
  IMotionVectorPredictor* _pMotionPredictor;        ///< Predictor for motion vector from neighbouring mbs.

	/// Vlc encoders and decoders for use with CAVLC.
	IVlcEncoder*	_pPrefixVlcEnc;
	IVlcDecoder*	_pPrefixVlcDec;
	IVlcEncoder*	_pCoeffTokenVlcEnc;
	IVlcDecoder*	_pCoeffTokenVlcDec;
	IVlcEncoder*	_pTotalZeros4x4VlcEnc;
	IVlcDecoder*	_pTotalZeros4x4VlcDec;
	IVlcEncoder*	_pTotalZeros2x2VlcEnc;
	IVlcDecoder*	_pTotalZeros2x2VlcDec;
	IVlcEncoder*	_pRunBeforeVlcEnc;
	IVlcDecoder*	_pRunBeforeVlcDec;
	/// ... and the remaining vlc encoders and decoders.
	IVlcEncoder*	_pBlkPattVlcEnc;
	IVlcDecoder*	_pBlkPattVlcDec;
	IVlcEncoder*	_pDeltaQPVlcEnc;
	IVlcDecoder*	_pDeltaQPVlcDec;
	IVlcEncoder*	_pMbTypeVlcEnc;
	IVlcDecoder*	_pMbTypeVlcDec;
	IVlcEncoder*	_pMbIChrPredModeVlcEnc;
	IVlcDecoder*	_pMbIChrPredModeVlcDec;
	IVlcEncoder*	_pMbMotionVecDiffVlcEnc;
	IVlcDecoder*	_pMbMotionVecDiffVlcDec;
	/// Context-Aware vlc codecs for each block size.
	IContextAwareRunLevelCodec* _pCAVLC4x4;
	IContextAwareRunLevelCodec* _pCAVLC2x2;
	/// General header vlc encoders and decoders.
	IVlcEncoder*	_pHeaderUnsignedVlcEnc;
	IVlcDecoder*	_pHeaderUnsignedVlcDec;
	IVlcEncoder*	_pHeaderSignedVlcEnc;
	IVlcDecoder*	_pHeaderSignedVlcDec;

	/// Macroblocks for the image.
	int								_mbLength;	///< No. of 16 x 16 macroblocks for this image size.
	MacroBlockH264*		_pMb;				///< Base macroblock linear reference.
	MacroBlockH264**	_Mb;				///< Macroblock 2-D reference.

	/// Internal picture properties. (For now)

	/// NAL unit definition.
	NalHeaderH264		_nal;
	/// Parameter sets with their current selections that reference the parameter arrays. 
	SeqParamSetH264	_seqParam[32];
	PicParamSetH264	_picParam[255];
  int             _encSeqParamByteLen;
  unsigned char   _pEncSeqParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded seq param set. (32 bytes)
  int             _encPicParamByteLen;
  unsigned char   _pEncPicParam[H264V2_ENC_PARAM_LEN];    ///< Cached current encoded pic param set. (32 bytes)

	/// H.264 has inter prediction mechanisms that permit multiple refrence pictures/frames and
	/// control parameters to maintain a list of these references. However, in this implementation
	/// the GOP are IPPPPPP..... and all P-frames use only the previous frame for reference. No
	/// reference lists (List0) are maintained and frame number counting is consecutively incremented
	/// from the previous IDR-frame.
	int						_frameNum;				///< Used for SliceHeader._frame_num
	int						_maxFrameNum;			///< Used for and derived from SeqParamSet._log2_max_frame_num_minus4
	int						_idrFrameNum;			///< Used for SliceHeader._idr_pic_id

	/// This implementation has only 1 slice for the entire frame without
	/// partitioning and therefore the slice parameters are simple.
	SliceHeaderH264	_slice;
	int							_mb_skip_run;		///< For P-Slices a skip run preceeds each macroblock.

	/// Image plane encoders/decoders. 
	IImagePlaneEncoder*		_pIntraImgPlaneEncoder;
	IImagePlaneEncoder*		_pInterImgPlaneEncoder;
	IImagePlaneDecoder*		_pIntraImgPlaneDecoder;
	IImagePlaneDecoder*		_pInterImgPlaneDecoder;

  /// Rate controllers and associated parameters.
  IRateControl*         _pRateCntlIFrames;
  IRateControl*         _pRateCntlPFrames;
  int                   _frameMSD;
  int                   _frameMAD;
  int                   _frameMAD_N;
  double                _predFrmMAD;
  int                   _avgBitsPerFrame;
  double                _coeffBitsPerPel;

  /// Region of Interest encoding parameters.
  double*               _roiMultiplier; ///< Multiply the distortion by a factor between 0.0..1.0 per macroblock.

  /// Motion lambda parameter for TCP-like adaptation.
  double                _mvLambda;  

#ifdef H264V2_DUMP
#ifdef H264V2_DUMP_HEADERS
  MeasurementTable _headerTable;
  int _headerTableLen;
  int _headerTablePos;
#endif
#ifdef H264V2_DUMP_MB_RD_DATA
  MeasurementTable _mbRDTable;
  int _mbRDTableLen;
  int _mbRDTablePos;
#endif
#ifdef H264V2_DUMP_TIMING
  MeasurementTable _timingTable;
  int _timingTableLen;
  int _timingTablePos;
#endif
#ifdef H264V2_DUMP_FRM_RD_DATA
  MeasurementTable _frmRDTable;
  int _frmRDTableLen;
  int _frmRDTablePos;
#endif
#endif

};//H264v2Codec class.


#endif	//end _H264V2CODEC_H
========== END FILE: H264v2Codec/old/H264v2Codec.h ==========

END SOURCE BUNDLE: 152 files
