git-svn-id: http://webrtc.googlecode.com/svn/trunk@3 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/common_video/OWNERS b/common_video/OWNERS
new file mode 100644
index 0000000..30eee35
--- /dev/null
+++ b/common_video/OWNERS
@@ -0,0 +1,4 @@
+holmer@google.com
+mikhal@google.com
+marpan@google.com
+hlundin@google.com
diff --git a/common_video/jpeg/main/interface/jpeg.h b/common_video/jpeg/main/interface/jpeg.h
new file mode 100644
index 0000000..6f092b8
--- /dev/null
+++ b/common_video/jpeg/main/interface/jpeg.h
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * JPEG wrapper
+ */
+
+#ifndef WEBRTC_COMMON_VIDEO_JPEG
+#define WEBRTC_COMMON_VIDEO_JPEG
+
+#include "typedefs.h"
+
+// jpeg forward declaration
+struct jpeg_compress_struct;
+struct jpeg_decompress_struct;
+
+namespace webrtc
+{
+
+class JpegEncoder
+{
+public:
+    JpegEncoder();
+    ~JpegEncoder();
+
+// SetFileName
+// Input:
+//  - fileName - Pointer to input vector (should be less than 256) to which the
+//               compressed  file will be written to
+//    Output:
+//    - 0             : OK
+//    - (-1)          : Error
+    WebRtc_Word32 SetFileName(const WebRtc_Word8* fileName);
+
+// Encode an I420 image. The encoded image is saved to a file
+//
+// Input:
+//          - inputImage        : Image to be encoded
+//
+//    Output:
+//    - 0             : OK
+//    - (-1)          : Error
+    WebRtc_Word32 Encode(const WebRtc_UWord8* imageBuffer,
+                         const WebRtc_UWord32 imageBufferSize,
+                         const WebRtc_UWord32 width,
+                         const WebRtc_UWord32 height);
+
+private:
+    WebRtc_Word32 Encode(const WebRtc_UWord8* imageBuffer,
+                         const WebRtc_UWord32 imageBufferSize);
+
+    jpeg_compress_struct*   _cinfo;
+    WebRtc_Word8            _fileName[256];
+    WebRtc_UWord32          _width;
+    WebRtc_UWord32          _height;
+};
+
+class JpegDecoder
+{
+ public:
+    JpegDecoder();
+    ~JpegDecoder();
+
+//Decodes a JPEG-stream
+//Supports 1 image component. 3 interleaved image components, YCbCr sub-sampling 4:4:4, 4:2:2, 4:2:0.
+//
+//Input:
+//    - encodedBuffer     : Pointer to the encoded stream to be decoded.
+//    - encodedBufferSize : Size of the data to be decoded
+//    - decodedBuffer     : Reference to the destination of the decoded I420-image.
+//    - width             : Reference returning width of decoded image.
+//    - height            : Reference returning height of decoded image.
+//
+//    Output:
+//    - 0             : OK
+//    - (-1)          : Error
+//Note: decodedBuffer should be freed by user
+    WebRtc_Word32 Decode(const WebRtc_UWord8* encodedBuffer,
+                         const WebRtc_UWord32 encodedBufferSize,
+                         WebRtc_UWord8*& decodedBuffer,
+                         WebRtc_UWord32& width,
+                         WebRtc_UWord32& height);
+ private:
+    jpeg_decompress_struct*    _cinfo;
+};
+
+
+}
+#endif /* WEBRTC_COMMON_VIDEO_JPEG  */
diff --git a/common_video/jpeg/main/source/data_manager.cc b/common_video/jpeg/main/source/data_manager.cc
new file mode 100644
index 0000000..2e2a870
--- /dev/null
+++ b/common_video/jpeg/main/source/data_manager.cc
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * data_manager.cc
+ */
+
+#include "data_manager.h"
+
+#ifdef WEBRTC_ANDROID
+extern "C" {
+#endif
+#include "jpeglib.h"
+#ifdef WEBRTC_ANDROID
+}
+#endif
+#include "jmorecfg.h"
+
+
+namespace webrtc
+{
+
+typedef struct
+{
+    jpeg_source_mgr  mgr;
+    JOCTET* next_input_byte;
+    size_t bytes_in_buffer;      /* # of byte spaces remaining in buffer */
+} DataSrcMgr;
+
+void
+jpegSetSrcBuffer(j_decompress_ptr cinfo, JOCTET* srcBuffer, size_t bufferSize)
+{
+    DataSrcMgr* src;
+    if (cinfo->src == NULL)
+    {  /* first time for this JPEG object? */
+        cinfo->src = (struct jpeg_source_mgr *)
+                   (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
+                       JPOOL_PERMANENT, sizeof(DataSrcMgr));
+    }
+
+    // Setting required functionality
+    src = (DataSrcMgr*) cinfo->src;
+    src->mgr.init_source = initSrc;;
+    src->mgr.fill_input_buffer = fillInputBuffer;
+    src->mgr.skip_input_data = skipInputData;
+    src->mgr.resync_to_restart = jpeg_resync_to_restart; // use default
+    src->mgr.term_source = termSource;
+    // setting buffer/src
+    src->bytes_in_buffer = bufferSize;
+    src->next_input_byte = srcBuffer;
+
+}
+
+
+void
+initSrc(j_decompress_ptr cinfo)
+{
+    DataSrcMgr  *src = (DataSrcMgr*)cinfo->src;
+    src->mgr.next_input_byte = src->next_input_byte;
+    src->mgr.bytes_in_buffer = src->bytes_in_buffer;
+}
+
+boolean
+fillInputBuffer(j_decompress_ptr cinfo)
+{
+    return false;
+}
+
+
+void
+skipInputData(j_decompress_ptr cinfo, long num_bytes)
+{
+    DataSrcMgr* src = (DataSrcMgr*)cinfo->src;
+    if (num_bytes > 0)
+    {
+          if ((unsigned long)num_bytes > src->mgr.bytes_in_buffer)
+              src->mgr.bytes_in_buffer = 0;
+          else
+          {
+              src->mgr.next_input_byte += num_bytes;
+              src->mgr.bytes_in_buffer -= num_bytes;
+          }
+    }
+}
+
+
+void
+termSource (j_decompress_ptr cinfo)
+{
+  //
+}
+
+} // end of namespace webrtc
diff --git a/common_video/jpeg/main/source/data_manager.h b/common_video/jpeg/main/source/data_manager.h
new file mode 100644
index 0000000..56fdb2d
--- /dev/null
+++ b/common_video/jpeg/main/source/data_manager.h
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * Jpeg source data manager
+ */
+
+#ifndef WEBRTC_COMMON_VIDEO_JPEG_DATA_MANAGER
+#define WEBRTC_COMMON_VIDEO_JPEG_DATA_MANAGER
+
+#include <stdio.h>
+
+// jpeg forward declaration
+struct jpeg_source_mgr;
+typedef unsigned char JOCTET;
+typedef int boolean;
+typedef struct jpeg_decompress_struct* j_decompress_ptr;
+typedef struct jpeg_compress_struct* j_compress_ptr;
+
+namespace webrtc
+{
+
+// Source manager:
+
+
+// a general function that will set these values
+void
+jpegSetSrcBuffer(j_decompress_ptr cinfo, JOCTET* srcBuffer, size_t bufferSize);
+
+
+// Initialize source.  This is called by jpeg_read_header() before any
+//  data is actually read.
+
+void
+initSrc(j_decompress_ptr cinfo);
+
+
+// Fill input buffer
+// This is called whenever bytes_in_buffer has reached zero and more
+//  data is wanted.
+
+boolean
+fillInputBuffer(j_decompress_ptr cinfo);
+
+// Skip input data
+// Skip num_bytes worth of data.
+
+void
+skipInputData(j_decompress_ptr cinfo, long num_bytes);
+
+
+
+
+// Terminate source
+void
+termSource (j_decompress_ptr cinfo);
+
+} // end of namespace webrtc
+
+
+#endif /* WEBRTC_COMMON_VIDEO_JPEG_DATA_MANAGER */
diff --git a/common_video/jpeg/main/source/jpeg.cc b/common_video/jpeg/main/source/jpeg.cc
new file mode 100644
index 0000000..9fffedd
--- /dev/null
+++ b/common_video/jpeg/main/source/jpeg.cc
@@ -0,0 +1,345 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * jpeg.cc
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vplib.h"
+#include "jpeg.h"
+#include "data_manager.h"
+#if defined(WIN32)
+ #include <basetsd.h>
+#endif
+#ifdef WEBRTC_ANDROID
+extern "C" {
+#endif
+#include "jpeglib.h"
+#ifdef WEBRTC_ANDROID
+}
+#endif
+#include <setjmp.h>
+
+
+namespace webrtc
+{
+
+// Error handler
+struct myErrorMgr {
+
+    struct jpeg_error_mgr pub;
+    jmp_buf setjmp_buffer;
+};
+typedef struct myErrorMgr * myErrorPtr;
+
+METHODDEF(void)
+MyErrorExit (j_common_ptr cinfo)
+{
+    myErrorPtr myerr = (myErrorPtr) cinfo->err;
+
+    // Return control to the setjmp point
+    longjmp(myerr->setjmp_buffer, 1);
+}
+
+JpegEncoder::JpegEncoder():
+_width(0),
+_height(0)
+{
+    _cinfo = new jpeg_compress_struct;
+    strcpy(_fileName, "Snapshot.jpg");
+}
+
+JpegEncoder::~JpegEncoder()
+{
+    delete _cinfo;
+    _cinfo = NULL;
+}
+
+
+WebRtc_Word32
+JpegEncoder::SetFileName(const WebRtc_Word8* fileName)
+{
+    if (!fileName)
+    {
+        return -1;
+    }
+
+    if (fileName)
+    {
+        strncpy(_fileName, fileName, 256);
+    }
+    return 0;
+}
+
+
+WebRtc_Word32
+JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
+                    const WebRtc_UWord32 imageBufferSize,
+                    const WebRtc_UWord32 width,
+                    const WebRtc_UWord32 height)
+{
+    if ((imageBuffer == NULL) || (imageBufferSize == 0))
+    {
+        return -1;
+    }
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    FILE* outFile = NULL;
+
+    _width = width;
+    _height = height;
+
+    // Set error handler
+    myErrorMgr      jerr;
+    _cinfo->err = jpeg_std_error(&jerr.pub);
+    jerr.pub.error_exit = MyErrorExit;
+    // Establish the setjmp return context
+    if (setjmp(jerr.setjmp_buffer))
+    {
+        // If we get here, the JPEG code has signaled an error.
+        jpeg_destroy_compress(_cinfo);
+        if (outFile != NULL)
+        {
+            fclose(outFile);
+        }
+        return -1;
+    }
+
+    if ((outFile = fopen(_fileName, "wb")) == NULL)
+    {
+        fprintf(stderr, "can't open %s\n", _fileName);
+        return -2;
+    }
+    // Create a compression object
+    jpeg_create_compress(_cinfo);
+
+    // Setting destination file
+    jpeg_stdio_dest(_cinfo, outFile);
+
+    WebRtc_Word32 ret = 0;
+
+    // Height of image buffer should be  a multiple of 16
+    if (_height % 16 == 0)
+    {
+        ret = Encode(imageBuffer, imageBufferSize);
+    }
+    else
+    {
+         WebRtc_UWord32 height16 = ((_height + 15) - 16) & - 16;
+         height16 = (height16 < _height) ? height16 + 16 : height16;
+
+         // Copy image to an adequate size buffer
+         WebRtc_UWord32 requiredSize = height16 * _width * 3 >> 1;
+         WebRtc_UWord8* origImagePtr = new WebRtc_UWord8[requiredSize];
+         if (origImagePtr == NULL)
+         {
+             return -1;
+         }
+         memset(origImagePtr, 0, requiredSize);
+         memcpy(origImagePtr, imageBuffer, imageBufferSize);
+
+         ret = Encode(origImagePtr, requiredSize);
+
+         // delete allocated buffer
+         delete [] origImagePtr;
+         origImagePtr = NULL;
+    }
+
+
+    fclose(outFile);
+
+    return ret;
+}
+
+WebRtc_Word32
+JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
+                    const WebRtc_UWord32 imageBufferSize)
+{
+    // Set parameters for compression
+    _cinfo->in_color_space = JCS_YCbCr;
+    jpeg_set_defaults(_cinfo);
+
+    _cinfo->image_width = _width;
+    _cinfo->image_height = _height;
+    _cinfo->input_components = 3;
+
+    _cinfo->comp_info[0].h_samp_factor = 2;   // Y
+    _cinfo->comp_info[0].v_samp_factor = 2;
+    _cinfo->comp_info[1].h_samp_factor = 1;   // U
+    _cinfo->comp_info[1].v_samp_factor = 1;
+    _cinfo->comp_info[2].h_samp_factor = 1;   // V
+    _cinfo->comp_info[2].v_samp_factor = 1;
+    _cinfo->raw_data_in = TRUE;
+
+    jpeg_start_compress(_cinfo, TRUE);
+
+    JSAMPROW y[16],u[8],v[8];
+    JSAMPARRAY data[3];
+
+    data[0] = y;
+    data[1] = u;
+    data[2] = v;
+
+    WebRtc_UWord32 i, j;
+
+    for (j = 0; j < _height; j += 16)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            y[i] = (JSAMPLE*) imageBuffer + _width * (i + j);
+
+            if (i % 2 == 0)
+            {
+                u[i / 2] = (JSAMPLE*) imageBuffer + _width * _height +
+                            _width / 2 * ((i + j) / 2);
+                v[i / 2] = (JSAMPLE*) imageBuffer + _width * _height +
+                            _width * _height / 4 + _width / 2 * ((i + j) / 2);
+            }
+        }
+            jpeg_write_raw_data(_cinfo, data, 16);
+    }
+
+    jpeg_finish_compress(_cinfo);
+    jpeg_destroy_compress(_cinfo);
+
+    return 0;
+}
+
+
+JpegDecoder::JpegDecoder()
+{
+    _cinfo = new jpeg_decompress_struct;
+}
+
+JpegDecoder::~JpegDecoder()
+{
+    delete _cinfo;
+    _cinfo = NULL;
+}
+
+WebRtc_Word32
+JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
+                    const WebRtc_UWord32 encodedBufferSize,
+                    WebRtc_UWord8*& decodedBuffer,
+                    WebRtc_UWord32& width,
+                    WebRtc_UWord32& height)
+{
+    // Set  error handler
+    myErrorMgr    jerr;
+    _cinfo->err = jpeg_std_error(&jerr.pub);
+    jerr.pub.error_exit = MyErrorExit;
+
+    // Establish the setjmp return context
+    if (setjmp(jerr.setjmp_buffer))
+    {
+        if (_cinfo->is_decompressor)
+        {
+            jpeg_destroy_decompress(_cinfo);
+        }
+        return -1;
+    }
+
+    _cinfo->out_color_space = JCS_YCbCr;
+
+    // Create decompression object
+    jpeg_create_decompress(_cinfo);
+
+    // Specify data source
+    jpegSetSrcBuffer(_cinfo, (JOCTET*) encodedBuffer, encodedBufferSize);
+
+    // Read header data
+    jpeg_read_header(_cinfo, TRUE);
+
+    _cinfo->raw_data_out = TRUE;
+    jpeg_start_decompress(_cinfo);
+
+    // Check header
+    if (_cinfo->num_components == 4)
+    {
+        return -2; // not supported
+    }
+    if (_cinfo->progressive_mode == 1)
+    {
+        return -2; // not supported
+    }
+
+    height = _cinfo->image_height;
+    width = _cinfo->image_width;
+
+    // Making sure width and height are even
+    if (height % 2)
+        height++;
+    if (width % 2)
+         width++;
+
+    WebRtc_UWord32 height16 = ((height + 15) - 16) & - 16;
+    height16 = (height16 < height) ? height16 + 16 : height16;
+
+    // allocate buffer to output
+    if (decodedBuffer != NULL)
+    {
+        delete [] decodedBuffer;
+        decodedBuffer = NULL;
+    }
+    decodedBuffer = new WebRtc_UWord8[width * height16 * 3 >> 1];
+    if (decodedBuffer == NULL)
+    {
+        return -1;
+    }
+
+    JSAMPROW y[16],u[8],v[8];
+    JSAMPARRAY data[3];
+    data[0] = y;
+    data[1] = u;
+    data[2] = v;
+
+    WebRtc_UWord32 hInd, i;
+    WebRtc_UWord32 numScanLines = 16;
+    WebRtc_UWord32 numLinesProcessed = 0;
+    while(_cinfo->output_scanline < _cinfo->output_height)
+    {
+        hInd = _cinfo->output_scanline;
+        for (i = 0; i < numScanLines; i++)
+        {
+            y[i] = decodedBuffer + width * (i + hInd);
+
+            if (i % 2 == 0)
+            {
+                 u[i / 2] = decodedBuffer + width * height +
+                            width / 2 * ((i + hInd) / 2);
+                 v[i / 2] = decodedBuffer + width * height +
+                            width * height / 4 + width / 2 * ((i + hInd) / 2);
+            }
+        }
+        // Processes exactly one iMCU row per call
+        numLinesProcessed = jpeg_read_raw_data(_cinfo, data, numScanLines);
+        // Error in read
+        if (numLinesProcessed == 0)
+        {
+            delete [] decodedBuffer;
+            jpeg_abort((j_common_ptr)_cinfo);
+            return -1;
+        }
+    }
+
+    jpeg_finish_decompress(_cinfo);
+    jpeg_destroy_decompress(_cinfo);
+    return 0;
+}
+
+
+}
diff --git a/common_video/jpeg/main/source/jpeg.gyp b/common_video/jpeg/main/source/jpeg.gyp
new file mode 100644
index 0000000..ad5419e
--- /dev/null
+++ b/common_video/jpeg/main/source/jpeg.gyp
@@ -0,0 +1,98 @@
+# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+  'includes': [
+    '../../../../common_settings.gypi', # Common settings
+  ],
+  'targets': [
+    {
+      'target_name': 'webrtc_jpeg',
+      'type': '<(library)',
+      'dependencies': [
+        '../../../vplib/main/source/vplib.gyp:webrtc_vplib',
+      ],
+      'include_dirs': [
+        '../interface',
+        '../../../../../../',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../interface',
+        ],
+      },
+      'conditions': [
+        ['build_with_chromium==1', {
+          'dependencies': [
+            '../../../../../libjpeg_turbo/libjpeg.gyp:libjpeg',
+          ],
+		  'include_dirs': [
+            '../../../../../libjpeg_turbo',
+          ],
+		  'direct_dependent_settings': {
+			'include_dirs': [
+			  '../../../../../libjpeg_turbo', 
+			],
+		  },
+        },{
+          'dependencies': [
+            '../../../../../third_party/libjpeg_turbo/libjpeg.gyp:libjpeg',
+          ],
+          'include_dirs': [
+            '../../../../third_party/libjpeg_turbo',
+          ],
+          'direct_dependent_settings': {
+			'include_dirs': [
+			  '../../../../third_party/libjpeg_turbo', 
+			],
+		  },
+        }],
+      ],
+      'sources': [
+        # interfaces
+        '../interface/jpeg.h',
+       
+        # headers
+        'data_manager.h',
+
+        # sources
+        'jpeg.cc',
+        'data_manager.cc',
+      ],
+    },
+    {
+      'target_name': 'jpeg_test',
+      'type': 'executable',
+      'dependencies': [
+         'webrtc_jpeg',
+      ],
+      'include_dirs': [
+         '../interface',
+         '../../../vplib/main/interface',
+         '../source',
+      ],
+      'sources': [
+
+        # headers
+        '../test/test_buffer.h',
+        
+        
+        # sources
+        '../test/test_buffer.cc',
+        '../test/test_jpeg.cc',
+
+      ], # source
+    },
+  ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/common_video/jpeg/main/test/test_buffer.cc b/common_video/jpeg/main/test/test_buffer.cc
new file mode 100644
index 0000000..98468f2
--- /dev/null
+++ b/common_video/jpeg/main/test/test_buffer.cc
@@ -0,0 +1,161 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// system includes
+#include <assert.h>
+#include <string.h>     // memcpy
+
+#include "test_buffer.h"
+#include "vplib.h"
+
+TestBuffer::TestBuffer():
+_buffer(0),
+_bufferSize(0),
+_bufferLength(0),
+_width(0),
+_height(0)
+{
+    //
+}
+
+TestBuffer::~TestBuffer()
+{
+    _bufferLength = 0;
+    _bufferSize = 0;
+    if(_buffer)
+    {
+        delete [] _buffer;
+        _buffer = 0;
+    }
+}
+
+TestBuffer::TestBuffer(const TestBuffer& rhs)
+:
+_bufferLength(rhs._bufferLength),
+_bufferSize(rhs._bufferSize),
+_height(rhs._height),
+_width(rhs._width),
+_buffer(0)
+{
+    // make sure that our buffer is big enough
+    _buffer = new WebRtc_UWord8[_bufferSize];
+    // only copy required length 
+    memcpy(_buffer, rhs._buffer, _bufferLength);
+}
+
+WebRtc_UWord32
+TestBuffer::GetWidth() const
+{
+    return _width;
+}
+
+WebRtc_UWord32
+TestBuffer::GetHeight() const
+{
+    return _height;
+}
+
+void            
+TestBuffer::SetWidth(WebRtc_UWord32 width)
+{
+    _width = width;
+}
+
+void            
+TestBuffer::SetHeight(WebRtc_UWord32 height)
+{
+    _height = height;
+}
+
+void
+TestBuffer::Free()
+{
+    _bufferLength = 0;
+    _bufferSize = 0;
+    _height = 0;
+    _width = 0;
+    if(_buffer)
+    {
+        delete [] _buffer;
+        _buffer = 0;
+    }
+}
+
+void
+TestBuffer::VerifyAndAllocate(WebRtc_UWord32 minimumSize)
+{
+    if(minimumSize > _bufferSize)
+    {
+        // make sure that our buffer is big enough
+        WebRtc_UWord8 * newBufferBuffer = new WebRtc_UWord8[minimumSize];
+        if(_buffer)
+        {
+            // copy the old data
+            memcpy(newBufferBuffer, _buffer, _bufferSize);
+            delete [] _buffer;
+        }
+        _buffer = newBufferBuffer;
+        _bufferSize = minimumSize;
+    }
+}
+
+void
+TestBuffer::UpdateLength(WebRtc_UWord32 newLength)
+{
+    assert(newLength <= _bufferSize);
+    _bufferLength = newLength;
+}
+
+void
+TestBuffer::CopyBuffer(WebRtc_UWord32 length, const WebRtc_UWord8* buffer)
+{
+    assert(length <= _bufferSize);
+     memcpy(_buffer, buffer, length);
+    _bufferLength = length;
+}
+
+void
+TestBuffer::CopyBuffer(TestBuffer& fromVideoBuffer)
+{
+    assert(fromVideoBuffer.GetLength() <= _bufferSize);
+    assert(fromVideoBuffer.GetSize() <= _bufferSize);
+    _bufferLength = fromVideoBuffer.GetLength();
+    _height = fromVideoBuffer.GetHeight();
+    _width = fromVideoBuffer.GetWidth();
+    memcpy(_buffer, fromVideoBuffer.GetBuffer(), fromVideoBuffer.GetLength());
+}
+
+void
+TestBuffer::Set(WebRtc_UWord8* tempBuffer,WebRtc_UWord32 tempSize, WebRtc_UWord32 tempLength)
+{
+    _buffer = tempBuffer;
+    _bufferSize = tempSize;
+    _bufferLength = tempLength;
+
+}
+
+WebRtc_UWord8*
+TestBuffer::GetBuffer() const
+{
+  return _buffer;
+}
+
+WebRtc_UWord32
+TestBuffer::GetSize() const
+{
+    return _bufferSize;
+}
+
+WebRtc_UWord32
+TestBuffer::GetLength() const
+{
+    return _bufferLength;
+}
+
diff --git a/common_video/jpeg/main/test/test_buffer.h b/common_video/jpeg/main/test/test_buffer.h
new file mode 100644
index 0000000..757fae3
--- /dev/null
+++ b/common_video/jpeg/main/test/test_buffer.h
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef WEBRTC_COMMON_VIDEO_JPEG_TEST_BUFFER_H
+#define WEBRTC_COMMON_VIDEO_JPEG_TEST_BUFFER_H
+
+#include "typedefs.h"
+
+class TestBuffer
+{
+public:
+    TestBuffer();
+
+    virtual ~TestBuffer();
+
+    TestBuffer(const TestBuffer& rhs);
+
+    /**
+     * Verifies that current allocated buffer size is larger than or equal to the input size.
+    * If the current buffer size is smaller, a new allocation is made and the old buffer data is copied to the new buffer.
+    */
+    void VerifyAndAllocate(WebRtc_UWord32 minimumSize);
+
+    void UpdateLength(WebRtc_UWord32 newLength);
+
+
+
+    void CopyBuffer(WebRtc_UWord32 length, const WebRtc_UWord8* fromBuffer);
+
+    void CopyBuffer(TestBuffer& fromBuffer);
+
+    void Free();    // Deletes frame buffer and resets members to zero
+
+    /**
+     *   Gets pointer to frame buffer
+     */
+    WebRtc_UWord8*    GetBuffer() const;
+
+    /**
+     *   Gets allocated buffer size
+     */
+    WebRtc_UWord32    GetSize() const;
+
+    /**
+     *   Gets length of frame
+     */
+    WebRtc_UWord32    GetLength() const;
+
+
+    WebRtc_UWord32    GetWidth() const;
+    WebRtc_UWord32    GetHeight() const;
+
+    void            SetWidth(WebRtc_UWord32 width);
+    void            SetHeight(WebRtc_UWord32 height);
+
+private:
+  //  TestBuffer& operator=(const TestBuffer& inBuffer);
+
+private:
+    void Set(WebRtc_UWord8* buffer,WebRtc_UWord32 size,WebRtc_UWord32 length);
+
+    WebRtc_UWord8*      _buffer;          // Pointer to frame buffer
+    WebRtc_UWord32      _bufferSize;      // Allocated buffer size
+    WebRtc_UWord32      _bufferLength;    // Length (in bytes) of frame
+    WebRtc_UWord32      _width;
+    WebRtc_UWord32      _height;
+};
+
+#endif
diff --git a/common_video/jpeg/main/test/test_jpeg.cc b/common_video/jpeg/main/test/test_jpeg.cc
new file mode 100644
index 0000000..a947dbd
--- /dev/null
+++ b/common_video/jpeg/main/test/test_jpeg.cc
@@ -0,0 +1,141 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * test_jpeg.cc
+ */
+
+#include <cassert>
+#include <iostream>
+#include <cmath>
+#include <string>
+#include <stdio.h>
+
+
+#include "test_buffer.h"
+#include "jpeg.h"
+
+using namespace webrtc;
+
+#define PRINT_LINE std::cout << "-------------------------------" << std::endl;
+
+int
+main(int argc, char **argv)
+{
+    if (argc < 1)
+    {
+        return -1;
+    }
+    std::string fileName = argv[1];
+    const char* fileNameDec = "TestJpegDec.yuv";
+    const char* fileNameEnc = "TestJpegEnc.jpg";
+
+    std::string str;
+    std::cout << "---------------------" << std::endl;
+    std::cout << "----- Test JPEG -----" << std::endl;
+    std::cout << "---------------------" << std::endl;
+    std::cout << "  "  << std::endl;
+
+
+    JpegDecoder* JpgDecPtr = new JpegDecoder( );
+
+    // Open input file
+    FILE* openFile = fopen(fileName.c_str(), "rb");
+    assert(openFile != NULL);
+
+    // Get file length
+    fseek(openFile, 0, SEEK_END);
+    int length = ftell(openFile);
+    fseek(openFile, 0, SEEK_SET);
+
+    // Read input file to buffer
+    TestBuffer encodedBuffer;
+    encodedBuffer.VerifyAndAllocate(length);
+    encodedBuffer.UpdateLength(length);
+    fread(encodedBuffer.GetBuffer(), 1, length, openFile);
+    fclose(openFile);
+
+    // ------------------
+    // Decode
+    // ------------------
+
+    TestBuffer imageBuffer;
+    WebRtc_UWord32 width = 0;
+    WebRtc_UWord32 height = 0;
+    WebRtc_UWord8* tmp = NULL;
+    int error = JpgDecPtr->Decode(encodedBuffer.GetBuffer(),
+                                  encodedBuffer.GetSize(), tmp, width, height);
+
+    std::cout << error << " = Decode(" << fileName.c_str() << ", (" << width <<
+        "x" << height << "))" << std::endl;
+    PRINT_LINE;
+
+    if (error == 0)
+    {
+        int imageBufferSize = width*height*3/2;
+        //update buffer info
+        imageBuffer.VerifyAndAllocate( imageBufferSize);
+        imageBuffer.CopyBuffer(imageBufferSize, tmp);
+        delete [] tmp;
+        // Save decoded image to file
+        FILE* saveFile = fopen(fileNameDec, "wb");
+        fwrite(imageBuffer.GetBuffer(), 1, imageBuffer.GetLength(), saveFile);
+        fclose(saveFile);
+
+        // ------------------
+        // Encode
+        // ------------------
+
+        JpegEncoder* JpegEncoderPtr = new JpegEncoder();
+
+        // Test invalid inputs
+
+        // Test buffer
+        TestBuffer empty;
+
+        int error = JpegEncoderPtr->SetFileName(0);
+        assert(error == -1);
+        error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
+                                       164, 164);
+        assert(error == -1);
+        error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
+                                       0, height);
+        assert(error == -1);
+        error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
+                                       width, 0);
+        assert(error == -1);
+
+        error = JpegEncoderPtr->SetFileName(fileNameEnc);
+        assert(error == 0);
+
+        // Actual Encode
+        error = JpegEncoderPtr->Encode(imageBuffer.GetBuffer(),
+                                       imageBuffer.GetSize(), width, height);
+        assert(error == 0);
+
+        std::cout << error << " = Encode(" << fileNameDec << ")" << std::endl;
+
+        PRINT_LINE;
+
+        delete JpegEncoderPtr;
+    }
+
+    imageBuffer.Free();
+    encodedBuffer.Free();
+    delete JpgDecPtr;
+
+    std::cout << "Verify that the encoded and decoded images look correct."
+        << std::endl;
+    std::cout << "Press enter to quit test...";
+    std::getline(std::cin, str);
+
+    return 0;
+}
+
diff --git a/common_video/vplib/main/interface/interpolator.h b/common_video/vplib/main/interface/interpolator.h
new file mode 100644
index 0000000..70ec4fa
--- /dev/null
+++ b/common_video/vplib/main/interface/interpolator.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * interpolator.h
+ * Interface to the WebRTC's interpolation functionality
+ */
+
+#ifndef WEBRTC_COMMON_VIDEO_INTERFACE_INTERPOLATOR_H
+#define WEBRTC_COMMON_VIDEO_INTERFACE_INTERPOLATOR_H
+
+#include "typedefs.h"
+#include "vplib.h"
+
+namespace webrtc
+{
+
+// supported interpolation types
+enum interpolatorType
+{
+    kBilinear
+};
+
+
+class interpolator
+{
+public:
+    interpolator();
+    ~interpolator();
+
+    // Set interpolation properties:
+    //
+    // Return value     : 0 if OK,
+    //                  : -1 - parameter error
+    //                  : -2 - general error
+    WebRtc_Word32 Set(WebRtc_UWord32 srcWidth, WebRtc_UWord32 srcHeight,
+                      WebRtc_UWord32 dstWidth, WebRtc_UWord32 dstHeight,
+                      VideoType srcVideoType, VideoType dstVideoType,
+                      interpolatorType type);
+
+    // Interpolate frame
+    //
+    // Return value     : Height of interpolated frame if OK,
+    //                  : -1 - parameter error
+    //                  : -2 - general error
+    WebRtc_Word32 Interpolate(const WebRtc_UWord8* srcFrame,
+                              WebRtc_UWord8*& dstFrame);
+
+private:
+
+    // Extract computation method given actual type
+    WebRtc_Word32 Method(interpolatorType type);
+
+    // Determine if the VideoTypes are currently supported
+    WebRtc_Word32 SupportedVideoType(VideoType srcVideoType,
+                                     VideoType dstVideoType);
+
+    interpolatorType        _method;
+    WebRtc_UWord32          _srcWidth;
+    WebRtc_UWord32          _srcHeight;
+    WebRtc_UWord32          _dstWidth;
+    WebRtc_UWord32          _dstHeight;
+};
+
+
+}  // namespace webrtc
+
+
+#endif  // WEBRTC_COMMON_VIDEO_INTERFACE_INTERPOLATOR_H
diff --git a/common_video/vplib/main/interface/vplib.h b/common_video/vplib/main/interface/vplib.h
new file mode 100644
index 0000000..79f96be
--- /dev/null
+++ b/common_video/vplib/main/interface/vplib.h
@@ -0,0 +1,356 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef WEBRTC_COMMON_VIDEO_INTERFACE_VPLIB_H
+#define WEBRTC_COMMON_VIDEO_INTERFACE_VPLIB_H
+
+
+#include "typedefs.h"
+
+namespace webrtc
+{
+
+// Supported video types
+enum VideoType
+{
+    kUnknown,
+    kI420,
+    kIYUV,
+    kRGB24,
+    kARGB,
+    kARGB4444,
+    kRGB565,
+    kARGB1555,
+    kYUY2,
+    kYV12,
+    kUYVY,
+    kMJPG,
+    kNV21,
+    kNV12,
+    kARGBMac,
+    kRGBAMac,
+
+    kNumberOfVideoTypes
+};
+
+
+// Supported rotation
+enum VideoRotationMode
+{
+    kRotateNone = 0,
+    kRotateClockwise = 90,
+    kRotateAntiClockwise = -90,
+    kRotate180 = 180,
+};
+
+
+    // Calculate the required buffer size
+    // Input
+    //    - type - The type of the designated video frame
+    //    - width - frame width in pixels
+    //    - height - frame height in pixels
+    // Output
+    //    - The required size in bytes to accommodate the specified video frame
+    //
+    WebRtc_UWord32 CalcBufferSize(VideoType type, WebRtc_UWord32 width, WebRtc_UWord32 height);
+
+
+    // Calculate the required buffer size when converting from one type to another
+    // Input
+    //   - incomingVideoType - The type of the existing video frame
+    //   - convertedVideoType - width of the designated video frame
+    //   - length - length in bytes of the data
+    // Output
+    //   - The required size in bytes to accommodate the specified converted video frame
+    //
+    WebRtc_UWord32 CalcBufferSize(VideoType incomingVideoType, VideoType convertedVideoType,
+                                  WebRtc_UWord32 length);
+
+    //
+    // Convert To/From I420
+    //
+    // The following 2 functions convert an image to/from a I420 type to/from a specified
+    // format.
+    //
+    // Input:
+    //    - incomingVideoType  : Type of input video
+    //    - incomingBuffer     : Pointer to an input image.
+    //    - width              : Image width in pixels.
+    //    - height             : Image height in pixels.
+    //    - outgoingBuffer     : Pointer to converted image.
+    //    - interlaced         : Flag indicating if interlaced I420 output
+    //    - rotate             : Rotation mode of output image
+    // Return value            : Size of converted image if OK, otherwise, the following error
+    //                           codes:
+    //                           -1 : Parameter error
+    //                           -2 : Unsupported command (parameter request)
+    //
+    // Note: the following functions includes the most common usage cases; for a more general
+    // usage, refer to explicit function
+    WebRtc_Word32 ConvertToI420(VideoType incomingVideoType,
+                                const WebRtc_UWord8* incomingBuffer,
+                                WebRtc_UWord32 width,
+                                WebRtc_UWord32 height,
+                                WebRtc_UWord8* outgoingBuffer,
+                                bool interlaced = false ,
+                                VideoRotationMode rotate  = kRotateNone
+                                );
+
+    WebRtc_Word32 ConvertFromI420(VideoType outgoingVideoType,
+                                  const WebRtc_UWord8* incomingBuffer,
+                                  WebRtc_UWord32 width,
+                                  WebRtc_UWord32 height,
+                                  WebRtc_UWord8* outgoingBuffer,
+                                  bool interlaced = false ,
+                                  VideoRotationMode rotate = kRotateNone
+                                  );
+
+    // Designated Convert Functions
+    // The following list describes the designated conversion function which are called by the
+    // 2 prior general conversion function.
+    // Input and output descriptions match the above descriptions, and are therefore omitted.
+    WebRtc_Word32 ConvertI420ToRGB24(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                     WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertI420ToARGB(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertI420ToARGB4444(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                        WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                        WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertI420ToRGB565(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                      WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertI420ToRGB565Android(const WebRtc_UWord8* inFrame,
+                                             WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                                             WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertI420ToARGB1555(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                        WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                        WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertI420ToARGBMac(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                       WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                       WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertI420ToRGBAMac(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                       WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                       WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertI420ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_UWord32 strideOut = 0);
+    WebRtc_Word32 ConvertI420ToUYVY(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_UWord32 strideOut = 0);
+    WebRtc_Word32 ConvertI420ToYUY2(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_UWord32 strideOut = 0);
+    WebRtc_Word32 ConvertI420ToYV12(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertYUY2ToI420interlaced(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                                              WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                                              WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight);
+    WebRtc_Word32 ConvertYV12ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 width,
+                                    WebRtc_UWord32 height, WebRtc_UWord8* outFrame);
+    WebRtc_Word32 ConvertRGB24ToARGB(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                     WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                     WebRtc_UWord32 strideOut);
+    WebRtc_Word32 ConvertRGB24ToI420(WebRtc_Word32 width, WebRtc_Word32 height,
+                                     const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame);
+    WebRtc_Word32 ConvertRGB565ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 width,
+                                      WebRtc_UWord32 height, WebRtc_UWord8* outFrame);
+    WebRtc_Word32 ConvertARGBMacToI420(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame);
+    WebRtc_Word32 ConvertUYVYToI420(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame);
+
+    // pad cut and convert
+    WebRtc_Word32 ConvertYUY2ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                                    WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight);
+    WebRtc_Word32 ConvertUYVYToI420interlaced(const WebRtc_UWord8* inFrame,
+                                              WebRtc_UWord32 inWidth, WebRtc_UWord32 inHeight,
+                                              WebRtc_UWord8* outFrame, WebRtc_UWord32 outWidth,
+                                              WebRtc_UWord32 outHeight);
+    WebRtc_Word32 ConvertRGB24ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                                     WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                                     WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight);
+    WebRtc_Word32 ConvertI420ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                                    WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight);
+
+    //NV12 Conversion/Rotation
+    WebRtc_Word32 ConvertNV12ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV12ToI420AndRotate180(const WebRtc_UWord8* inFrame,
+                                                WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                                                WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV12ToI420AndRotateAntiClockwise(const WebRtc_UWord8* inFrame,
+                                                          WebRtc_UWord8* outFrame,
+                                                          WebRtc_UWord32 width,
+                                                          WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV12ToI420AndRotateClockwise(const WebRtc_UWord8* inFrame,
+                                                      WebRtc_UWord8* outFrame,
+                                                      WebRtc_UWord32 width,
+                                                      WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV12ToRGB565(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                      WebRtc_UWord32 width, WebRtc_UWord32 height);
+
+    //NV21 Conversion/Rotation
+    WebRtc_Word32 ConvertNV21ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV21ToI420AndRotate180(const WebRtc_UWord8* inFrame,
+                                                WebRtc_UWord8* outFrame,
+                                                WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV21ToI420AndRotateAntiClockwise(const WebRtc_UWord8* inFrame,
+                                                          WebRtc_UWord8* outFrame,
+                                                          WebRtc_UWord32 width,
+                                                          WebRtc_UWord32 height);
+    WebRtc_Word32 ConvertNV21ToI420AndRotateClockwise(const WebRtc_UWord8* inFrame,
+                                                      WebRtc_UWord8* outFrame,
+                                                      WebRtc_UWord32 width,
+                                                      WebRtc_UWord32 height);
+
+    //IPhone
+    WebRtc_Word32 ConvertI420ToRGBAIPhone(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                          WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                          WebRtc_UWord32 strideOut);
+
+    // I420 Cut and Pad - make a center cut
+    WebRtc_Word32 CutI420Frame(WebRtc_UWord8* frame, WebRtc_UWord32 fromWidth,
+                               WebRtc_UWord32 fromHeight, WebRtc_UWord32 toWidth,
+                               WebRtc_UWord32 toHeight);
+
+    // Pad an I420 frame
+    // Input:
+    //    - inBuffer       : Pointer to the input image component to be padded.
+    //    - outBuffer      : Pointer to the output padded image component.
+    //    - fromWidth      : Width in pixels of the inBuffer component.
+    //    - fromHeight     : Height in pixels of the inBuffer component.
+    //    - toWidth        : Width in pixels of the outBuffer component.
+    //    - toHeight       : Height in pixels of the outBuffer component.
+    // Return Value:
+    //      - Length of the output component.
+    WebRtc_Word32 PadI420Frame(const WebRtc_UWord8* inBuffer, WebRtc_UWord8* outBuffer,
+                               WebRtc_UWord32 fromWidth, WebRtc_UWord32 fromHeight,
+                               WebRtc_UWord32 toWidth, WebRtc_UWord32 toHeight);
+    WebRtc_Word32 PadI420BottomRows(WebRtc_UWord8* buffer, WebRtc_UWord32 size,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                    WebRtc_Word32 nrRows, WebRtc_UWord32& newLength);
+
+    // I420 Scale
+    // Scale an I420 frame:Half frame, quarter frame
+    // Input:
+    //    - inFrame     : Pointer to the image component to be scaled
+    //    - width          : Width in pixels of the output frame.
+    //    - height         : Height in pixels of the out frame.
+    // Return Value:
+    //      - Length of the output component.
+    WebRtc_Word32 ScaleI420FrameQuarter(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                        WebRtc_UWord8* inFrame);
+    WebRtc_Word32 ScaleI420DownHalfFrame(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                         WebRtc_UWord8* inFrame);
+    WebRtc_Word32 ScaleI420UpHalfFrame(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                       WebRtc_UWord8* inFrame);
+
+    // Scales up an I420-frame to twice its width and height. Interpolates by using mean value
+    // of neighboring pixels.
+    // The following two function allow up-scaling by either twice or 3/2 of the original
+    // the width and height
+    // Input:
+    //    - width          : Width of input frame in pixels.
+    //    - height         : Height of input frame in pixels.
+    //    - buffer         : Reference to a buffer containing the frame.
+    //    - size           :Size of allocated buffer
+    //    - scaledWidth    : Reference to the width of scaled frame in pixels.
+    //    - scaledHeight   : Reference to the height of scaled frame in pixels.
+    // Return value:
+    //    - (length)       : Length of scaled frame.
+    //    - (-1)           : Error.
+    WebRtc_Word32 ScaleI420Up2(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                               WebRtc_UWord8*& buffer, WebRtc_UWord32 size,
+                               WebRtc_UWord32 &scaledWidth, WebRtc_UWord32 &scaledHeight);
+    WebRtc_Word32 ScaleI420Up3_2(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                 WebRtc_UWord8*& buffer, WebRtc_UWord32 size,
+                                 WebRtc_UWord32 &scaledWidth, WebRtc_UWord32 &scaledHeight);
+
+    // Scales down an I420-frame to one third its width and height.
+    // Input:
+    //    - width          : Width of frame in pixels.
+    //    - height         : Height of frame in pixels.
+    //    - videoBuffer    : Reference to a buffer containing the frame.
+    //    - scaledWidth    : Width of scaled frame in pixels.
+    //    - scaledHeight   : Height of scaled frame in pixels.
+    // Return value:
+    //    - (length)       : Length of scaled frame.
+    //    - (-1)           : Error.
+    WebRtc_Word32 ScaleI420Down1_3(WebRtc_UWord32 width, WebRtc_UWord32 height,
+                                   WebRtc_UWord8*& buffer, WebRtc_UWord32 size,
+                                   WebRtc_UWord32 &scaledWidth, WebRtc_UWord32 &scaledHeight);
+
+    // Convert From I420/YV12 to I420 and Rotate clockwise
+    // Input:
+    //    - srcBuffer    : Reference to a buffer containing the source frame.
+    //    - srcWidth     : Width of source frame in pixels.
+    //    - srcHeight    : Height of source frame in pixels.
+    //    - dstBuffer    : Reference to a buffer containing the destination frame.
+    //    - dstWidth     : Width of destination frame in pixels.
+    //    - dstHeight    : Height of destination frame in pixels.
+    //    - colorSpaceIn : Input color space
+    // Return value:
+    //    - (length)       : Length of scaled frame.
+    //    - (-1)           : Error.
+    WebRtc_Word32 ConvertToI420AndRotateClockwise(const WebRtc_UWord8* srcBuffer,
+                                                  WebRtc_UWord32 srcWidth,
+                                                  WebRtc_UWord32 srcHeight,
+                                                  WebRtc_UWord8* dstBuffer,
+                                                  WebRtc_UWord32 dstWidth,
+                                                  WebRtc_UWord32 dstHeight,
+                                                  VideoType colorSpaceIn);
+
+    // Convert From I420/YV12 to I420 and Rotate anti clockwise
+    // Inputs/outputs as the above function
+    WebRtc_Word32 ConvertToI420AndRotateAntiClockwise(const WebRtc_UWord8* srcBuffer,
+                                                      WebRtc_UWord32 srcWidth,
+                                                      WebRtc_UWord32 srcHeight,
+                                                      WebRtc_UWord8* dstBuffer,
+                                                      WebRtc_UWord32 dstWidth,
+                                                      WebRtc_UWord32 dstHeight,
+                                                      VideoType colorSpaceIn);
+
+    // Mirror functions
+    // The following 2 functions perform mirroring on a given image (LeftRight/UpDown)
+    // Input:
+    //    - width       : Image width in pixels.
+    //    - height      : Image height in pixels.
+    //    - inFrame     : Reference to input image.
+    //    - outFrame    : Reference to converted image.
+    // Return value: 0 if OK, < 0 otherwise.
+    WebRtc_Word32 MirrorI420LeftRight(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                      WebRtc_UWord32 width, WebRtc_UWord32 height);
+    WebRtc_Word32 MirrorI420UpDown(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                   WebRtc_UWord32 width, WebRtc_UWord32 height);
+
+    // Mirror functions - Don't work in place (srcBuffer == dstBuffer),
+    // and are therefore faster. Also combine mirroring with conversion to speed things up.
+    // Input:
+    //    - srcBuffer       : Pointer to source image.
+    //    - dstBuffer       : Pointer to destination image.
+    //    - srcWidth        : Width of input buffer.
+    //    - srcHeight       : Height of input buffer.
+    //    - colorSpaceIn    : Color space to convert from, I420 if no conversion should be done
+    //    - dstBuffer       : Pointer to converted/rotated image.
+    // Return value:      0 if OK, < 0 otherwise.
+    WebRtc_Word32 ConvertToI420AndMirrorUpDown(const WebRtc_UWord8* srcBuffer,
+                                               WebRtc_UWord8* dstBuffer,
+                                               WebRtc_UWord32 srcWidth,
+                                               WebRtc_UWord32 srcHeight,
+                                               VideoType colorSpaceIn = kI420);
+
+}
+
+#endif
diff --git a/common_video/vplib/main/source/conversion_tables.h b/common_video/vplib/main/source/conversion_tables.h
new file mode 100644
index 0000000..4f3b1ec
--- /dev/null
+++ b/common_video/vplib/main/source/conversion_tables.h
@@ -0,0 +1,182 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/**************************************************************
+*  conversion_tables.h
+*
+*    Pre-compiled definitions of the conversion equations: YUV -> RGB.
+*    
+***************************************************************/
+
+#ifndef WEBRTC_COMMON_VIDEO_VPLIB_CONVERSION_TABLES
+#define WEBRTC_COMMON_VIDEO_VPLIB_CONVERSION_TABLES
+
+#include "typedefs.h"
+namespace webrtc
+{
+/*********************************************************************************************
+* YUV TO RGB approximation
+*
+*         R = clip( (298 * (Y - 16)                   + 409 * (V - 128) + 128 ) >> 8 )
+*         G = clip( (298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128 ) >> 8 )  
+*         B = clip( (298 * (Y - 16) + 516 * (U - 128)                   + 128 ) >> 8 )      
+**********************************************************************************************/
+
+    #define Yc(i)  static_cast<WebRtc_Word32> ( 298  * ( i - 16 ))     // Y contribution
+    #define Ucg(i) static_cast<WebRtc_Word32> ( -100 * ( i - 128 ))    // U contribution to G
+    #define Ucb(i) static_cast<WebRtc_Word32> ( 516  * ( i - 128 ))    // U contribution to B
+    #define Vcr(i) static_cast<WebRtc_Word32> ( 409  * ( i - 128 ))    // V contribution to R
+    #define Vcg(i) static_cast<WebRtc_Word32> ( -208 * ( i - 128 ))    // V contribution to G
+
+    static const WebRtc_Word32 mapYc[256] = {
+        Yc(0),Yc(1),Yc(2),Yc(3),Yc(4),Yc(5),Yc(6),Yc(7),Yc(8),Yc(9),
+        Yc(10),Yc(11),Yc(12),Yc(13),Yc(14),Yc(15),Yc(16),Yc(17),Yc(18),Yc(19),
+        Yc(20),Yc(21),Yc(22),Yc(23),Yc(24),Yc(25),Yc(26),Yc(27),Yc(28),Yc(29),
+        Yc(30),Yc(31),Yc(32),Yc(33),Yc(34),Yc(35),Yc(36),Yc(37),Yc(38),Yc(39),
+        Yc(40),Yc(41),Yc(42),Yc(43),Yc(44),Yc(45),Yc(46),Yc(47),Yc(48),Yc(49),
+        Yc(50),Yc(51),Yc(52),Yc(53),Yc(54),Yc(55),Yc(56),Yc(57),Yc(58),Yc(59),
+        Yc(60),Yc(61),Yc(62),Yc(63),Yc(64),Yc(65),Yc(66),Yc(67),Yc(68),Yc(69),
+        Yc(70),Yc(71),Yc(72),Yc(73),Yc(74),Yc(75),Yc(76),Yc(77),Yc(78),Yc(79),
+        Yc(80),Yc(81),Yc(82),Yc(83),Yc(84),Yc(85),Yc(86),Yc(87),Yc(88),Yc(89),
+        Yc(90),Yc(91),Yc(92),Yc(93),Yc(94),Yc(95),Yc(96),Yc(97),Yc(98),Yc(99),
+        Yc(100),Yc(101),Yc(102),Yc(103),Yc(104),Yc(105),Yc(106),Yc(107),Yc(108),Yc(109),
+        Yc(110),Yc(111),Yc(112),Yc(113),Yc(114),Yc(115),Yc(116),Yc(117),Yc(118),Yc(119),
+        Yc(120),Yc(121),Yc(122),Yc(123),Yc(124),Yc(125),Yc(126),Yc(127),Yc(128),Yc(129),
+        Yc(130),Yc(131),Yc(132),Yc(133),Yc(134),Yc(135),Yc(136),Yc(137),Yc(138),Yc(139),
+        Yc(140),Yc(141),Yc(142),Yc(143),Yc(144),Yc(145),Yc(146),Yc(147),Yc(148),Yc(149),
+        Yc(150),Yc(151),Yc(152),Yc(153),Yc(154),Yc(155),Yc(156),Yc(157),Yc(158),Yc(159),
+        Yc(160),Yc(161),Yc(162),Yc(163),Yc(164),Yc(165),Yc(166),Yc(167),Yc(168),Yc(169),
+        Yc(170),Yc(171),Yc(172),Yc(173),Yc(174),Yc(175),Yc(176),Yc(177),Yc(178),Yc(179),
+        Yc(180),Yc(181),Yc(182),Yc(183),Yc(184),Yc(185),Yc(186),Yc(187),Yc(188),Yc(189),
+        Yc(190),Yc(191),Yc(192),Yc(193),Yc(194),Yc(195),Yc(196),Yc(197),Yc(198),Yc(199),
+        Yc(200),Yc(201),Yc(202),Yc(203),Yc(204),Yc(205),Yc(206),Yc(207),Yc(208),Yc(209),
+        Yc(210),Yc(211),Yc(212),Yc(213),Yc(214),Yc(215),Yc(216),Yc(217),Yc(218),Yc(219),
+        Yc(220),Yc(221),Yc(222),Yc(223),Yc(224),Yc(225),Yc(226),Yc(227),Yc(228),Yc(229),
+        Yc(230),Yc(231),Yc(232),Yc(233),Yc(234),Yc(235),Yc(236),Yc(237),Yc(238),Yc(239),
+        Yc(240),Yc(241),Yc(242),Yc(243),Yc(244),Yc(245),Yc(246),Yc(247),Yc(248),Yc(249),
+        Yc(250),Yc(251),Yc(252),Yc(253),Yc(254),Yc(255)};
+
+   static const WebRtc_Word32 mapUcg[256] = {
+        Ucg(0),Ucg(1),Ucg(2),Ucg(3),Ucg(4),Ucg(5),Ucg(6),Ucg(7),Ucg(8),Ucg(9),
+        Ucg(10),Ucg(11),Ucg(12),Ucg(13),Ucg(14),Ucg(15),Ucg(16),Ucg(17),Ucg(18),Ucg(19),
+        Ucg(20),Ucg(21),Ucg(22),Ucg(23),Ucg(24),Ucg(25),Ucg(26),Ucg(27),Ucg(28),Ucg(29),
+        Ucg(30),Ucg(31),Ucg(32),Ucg(33),Ucg(34),Ucg(35),Ucg(36),Ucg(37),Ucg(38),Ucg(39),
+        Ucg(40),Ucg(41),Ucg(42),Ucg(43),Ucg(44),Ucg(45),Ucg(46),Ucg(47),Ucg(48),Ucg(49),
+        Ucg(50),Ucg(51),Ucg(52),Ucg(53),Ucg(54),Ucg(55),Ucg(56),Ucg(57),Ucg(58),Ucg(59),
+        Ucg(60),Ucg(61),Ucg(62),Ucg(63),Ucg(64),Ucg(65),Ucg(66),Ucg(67),Ucg(68),Ucg(69),
+        Ucg(70),Ucg(71),Ucg(72),Ucg(73),Ucg(74),Ucg(75),Ucg(76),Ucg(77),Ucg(78),Ucg(79),
+        Ucg(80),Ucg(81),Ucg(82),Ucg(83),Ucg(84),Ucg(85),Ucg(86),Ucg(87),Ucg(88),Ucg(89),
+        Ucg(90),Ucg(91),Ucg(92),Ucg(93),Ucg(94),Ucg(95),Ucg(96),Ucg(97),Ucg(98),Ucg(99),
+        Ucg(100),Ucg(101),Ucg(102),Ucg(103),Ucg(104),Ucg(105),Ucg(106),Ucg(107),Ucg(108),Ucg(109),
+        Ucg(110),Ucg(111),Ucg(112),Ucg(113),Ucg(114),Ucg(115),Ucg(116),Ucg(117),Ucg(118),Ucg(119),
+        Ucg(120),Ucg(121),Ucg(122),Ucg(123),Ucg(124),Ucg(125),Ucg(126),Ucg(127),Ucg(128),Ucg(129),
+        Ucg(130),Ucg(131),Ucg(132),Ucg(133),Ucg(134),Ucg(135),Ucg(136),Ucg(137),Ucg(138),Ucg(139),
+        Ucg(140),Ucg(141),Ucg(142),Ucg(143),Ucg(144),Ucg(145),Ucg(146),Ucg(147),Ucg(148),Ucg(149),
+        Ucg(150),Ucg(151),Ucg(152),Ucg(153),Ucg(154),Ucg(155),Ucg(156),Ucg(157),Ucg(158),Ucg(159),
+        Ucg(160),Ucg(161),Ucg(162),Ucg(163),Ucg(164),Ucg(165),Ucg(166),Ucg(167),Ucg(168),Ucg(169),
+        Ucg(170),Ucg(171),Ucg(172),Ucg(173),Ucg(174),Ucg(175),Ucg(176),Ucg(177),Ucg(178),Ucg(179),
+        Ucg(180),Ucg(181),Ucg(182),Ucg(183),Ucg(184),Ucg(185),Ucg(186),Ucg(187),Ucg(188),Ucg(189),
+        Ucg(190),Ucg(191),Ucg(192),Ucg(193),Ucg(194),Ucg(195),Ucg(196),Ucg(197),Ucg(198),Ucg(199),
+        Ucg(200),Ucg(201),Ucg(202),Ucg(203),Ucg(204),Ucg(205),Ucg(206),Ucg(207),Ucg(208),Ucg(209),
+        Ucg(210),Ucg(211),Ucg(212),Ucg(213),Ucg(214),Ucg(215),Ucg(216),Ucg(217),Ucg(218),Ucg(219),
+        Ucg(220),Ucg(221),Ucg(222),Ucg(223),Ucg(224),Ucg(225),Ucg(226),Ucg(227),Ucg(228),Ucg(229),
+        Ucg(230),Ucg(231),Ucg(232),Ucg(233),Ucg(234),Ucg(235),Ucg(236),Ucg(237),Ucg(238),Ucg(239),
+        Ucg(240),Ucg(241),Ucg(242),Ucg(243),Ucg(244),Ucg(245),Ucg(246),Ucg(247),Ucg(248),Ucg(249),
+        Ucg(250),Ucg(251),Ucg(252),Ucg(253),Ucg(254),Ucg(255)};
+        
+
+   static const WebRtc_Word32 mapUcb[256] = {
+        Ucb(0),Ucb(1),Ucb(2),Ucb(3),Ucb(4),Ucb(5),Ucb(6),Ucb(7),Ucb(8),Ucb(9),
+        Ucb(10),Ucb(11),Ucb(12),Ucb(13),Ucb(14),Ucb(15),Ucb(16),Ucb(17),Ucb(18),Ucb(19),
+        Ucb(20),Ucb(21),Ucb(22),Ucb(23),Ucb(24),Ucb(25),Ucb(26),Ucb(27),Ucb(28),Ucb(29),
+        Ucb(30),Ucb(31),Ucb(32),Ucb(33),Ucb(34),Ucb(35),Ucb(36),Ucb(37),Ucb(38),Ucb(39),
+        Ucb(40),Ucb(41),Ucb(42),Ucb(43),Ucb(44),Ucb(45),Ucb(46),Ucb(47),Ucb(48),Ucb(49),
+        Ucb(50),Ucb(51),Ucb(52),Ucb(53),Ucb(54),Ucb(55),Ucb(56),Ucb(57),Ucb(58),Ucb(59),
+        Ucb(60),Ucb(61),Ucb(62),Ucb(63),Ucb(64),Ucb(65),Ucb(66),Ucb(67),Ucb(68),Ucb(69),
+        Ucb(70),Ucb(71),Ucb(72),Ucb(73),Ucb(74),Ucb(75),Ucb(76),Ucb(77),Ucb(78),Ucb(79),
+        Ucb(80),Ucb(81),Ucb(82),Ucb(83),Ucb(84),Ucb(85),Ucb(86),Ucb(87),Ucb(88),Ucb(89),
+        Ucb(90),Ucb(91),Ucb(92),Ucb(93),Ucb(94),Ucb(95),Ucb(96),Ucb(97),Ucb(98),Ucb(99),
+        Ucb(100),Ucb(101),Ucb(102),Ucb(103),Ucb(104),Ucb(105),Ucb(106),Ucb(107),Ucb(108),Ucb(109),
+        Ucb(110),Ucb(111),Ucb(112),Ucb(113),Ucb(114),Ucb(115),Ucb(116),Ucb(117),Ucb(118),Ucb(119),
+        Ucb(120),Ucb(121),Ucb(122),Ucb(123),Ucb(124),Ucb(125),Ucb(126),Ucb(127),Ucb(128),Ucb(129),
+        Ucb(130),Ucb(131),Ucb(132),Ucb(133),Ucb(134),Ucb(135),Ucb(136),Ucb(137),Ucb(138),Ucb(139),
+        Ucb(140),Ucb(141),Ucb(142),Ucb(143),Ucb(144),Ucb(145),Ucb(146),Ucb(147),Ucb(148),Ucb(149),
+        Ucb(150),Ucb(151),Ucb(152),Ucb(153),Ucb(154),Ucb(155),Ucb(156),Ucb(157),Ucb(158),Ucb(159),
+        Ucb(160),Ucb(161),Ucb(162),Ucb(163),Ucb(164),Ucb(165),Ucb(166),Ucb(167),Ucb(168),Ucb(169),
+        Ucb(170),Ucb(171),Ucb(172),Ucb(173),Ucb(174),Ucb(175),Ucb(176),Ucb(177),Ucb(178),Ucb(179),
+        Ucb(180),Ucb(181),Ucb(182),Ucb(183),Ucb(184),Ucb(185),Ucb(186),Ucb(187),Ucb(188),Ucb(189),
+        Ucb(190),Ucb(191),Ucb(192),Ucb(193),Ucb(194),Ucb(195),Ucb(196),Ucb(197),Ucb(198),Ucb(199),
+        Ucb(200),Ucb(201),Ucb(202),Ucb(203),Ucb(204),Ucb(205),Ucb(206),Ucb(207),Ucb(208),Ucb(209),
+        Ucb(210),Ucb(211),Ucb(212),Ucb(213),Ucb(214),Ucb(215),Ucb(216),Ucb(217),Ucb(218),Ucb(219),
+        Ucb(220),Ucb(221),Ucb(222),Ucb(223),Ucb(224),Ucb(225),Ucb(226),Ucb(227),Ucb(228),Ucb(229),
+        Ucb(230),Ucb(231),Ucb(232),Ucb(233),Ucb(234),Ucb(235),Ucb(236),Ucb(237),Ucb(238),Ucb(239),
+        Ucb(240),Ucb(241),Ucb(242),Ucb(243),Ucb(244),Ucb(245),Ucb(246),Ucb(247),Ucb(248),Ucb(249),
+        Ucb(250),Ucb(251),Ucb(252),Ucb(253),Ucb(254),Ucb(255)};
+
+    static const WebRtc_Word32 mapVcr[256] = {
+        Vcr(0),Vcr(1),Vcr(2),Vcr(3),Vcr(4),Vcr(5),Vcr(6),Vcr(7),Vcr(8),Vcr(9),
+        Vcr(10),Vcr(11),Vcr(12),Vcr(13),Vcr(14),Vcr(15),Vcr(16),Vcr(17),Vcr(18),Vcr(19),
+        Vcr(20),Vcr(21),Vcr(22),Vcr(23),Vcr(24),Vcr(25),Vcr(26),Vcr(27),Vcr(28),Vcr(29),
+        Vcr(30),Vcr(31),Vcr(32),Vcr(33),Vcr(34),Vcr(35),Vcr(36),Vcr(37),Vcr(38),Vcr(39),
+        Vcr(40),Vcr(41),Vcr(42),Vcr(43),Vcr(44),Vcr(45),Vcr(46),Vcr(47),Vcr(48),Vcr(49),
+        Vcr(50),Vcr(51),Vcr(52),Vcr(53),Vcr(54),Vcr(55),Vcr(56),Vcr(57),Vcr(58),Vcr(59),
+        Vcr(60),Vcr(61),Vcr(62),Vcr(63),Vcr(64),Vcr(65),Vcr(66),Vcr(67),Vcr(68),Vcr(69),
+        Vcr(70),Vcr(71),Vcr(72),Vcr(73),Vcr(74),Vcr(75),Vcr(76),Vcr(77),Vcr(78),Vcr(79),
+        Vcr(80),Vcr(81),Vcr(82),Vcr(83),Vcr(84),Vcr(85),Vcr(86),Vcr(87),Vcr(88),Vcr(89),
+        Vcr(90),Vcr(91),Vcr(92),Vcr(93),Vcr(94),Vcr(95),Vcr(96),Vcr(97),Vcr(98),Vcr(99),
+        Vcr(100),Vcr(101),Vcr(102),Vcr(103),Vcr(104),Vcr(105),Vcr(106),Vcr(107),Vcr(108),Vcr(109),
+        Vcr(110),Vcr(111),Vcr(112),Vcr(113),Vcr(114),Vcr(115),Vcr(116),Vcr(117),Vcr(118),Vcr(119),
+        Vcr(120),Vcr(121),Vcr(122),Vcr(123),Vcr(124),Vcr(125),Vcr(126),Vcr(127),Vcr(128),Vcr(129),
+        Vcr(130),Vcr(131),Vcr(132),Vcr(133),Vcr(134),Vcr(135),Vcr(136),Vcr(137),Vcr(138),Vcr(139),
+        Vcr(140),Vcr(141),Vcr(142),Vcr(143),Vcr(144),Vcr(145),Vcr(146),Vcr(147),Vcr(148),Vcr(149),
+        Vcr(150),Vcr(151),Vcr(152),Vcr(153),Vcr(154),Vcr(155),Vcr(156),Vcr(157),Vcr(158),Vcr(159),
+        Vcr(160),Vcr(161),Vcr(162),Vcr(163),Vcr(164),Vcr(165),Vcr(166),Vcr(167),Vcr(168),Vcr(169),
+        Vcr(170),Vcr(171),Vcr(172),Vcr(173),Vcr(174),Vcr(175),Vcr(176),Vcr(177),Vcr(178),Vcr(179),
+        Vcr(180),Vcr(181),Vcr(182),Vcr(183),Vcr(184),Vcr(185),Vcr(186),Vcr(187),Vcr(188),Vcr(189),
+        Vcr(190),Vcr(191),Vcr(192),Vcr(193),Vcr(194),Vcr(195),Vcr(196),Vcr(197),Vcr(198),Vcr(199),
+        Vcr(200),Vcr(201),Vcr(202),Vcr(203),Vcr(204),Vcr(205),Vcr(206),Vcr(207),Vcr(208),Vcr(209),
+        Vcr(210),Vcr(211),Vcr(212),Vcr(213),Vcr(214),Vcr(215),Vcr(216),Vcr(217),Vcr(218),Vcr(219),
+        Vcr(220),Vcr(221),Vcr(222),Vcr(223),Vcr(224),Vcr(225),Vcr(226),Vcr(227),Vcr(228),Vcr(229),
+        Vcr(230),Vcr(231),Vcr(232),Vcr(233),Vcr(234),Vcr(235),Vcr(236),Vcr(237),Vcr(238),Vcr(239),
+        Vcr(240),Vcr(241),Vcr(242),Vcr(243),Vcr(244),Vcr(245),Vcr(246),Vcr(247),Vcr(248),Vcr(249),
+        Vcr(250),Vcr(251),Vcr(252),Vcr(253),Vcr(254),Vcr(255)};
+
+
+         static const WebRtc_Word32 mapVcg[256] = {
+        Vcg(0),Vcg(1),Vcg(2),Vcg(3),Vcg(4),Vcg(5),Vcg(6),Vcg(7),Vcg(8),Vcg(9),
+        Vcg(10),Vcg(11),Vcg(12),Vcg(13),Vcg(14),Vcg(15),Vcg(16),Vcg(17),Vcg(18),Vcg(19),
+        Vcg(20),Vcg(21),Vcg(22),Vcg(23),Vcg(24),Vcg(25),Vcg(26),Vcg(27),Vcg(28),Vcg(29),
+        Vcg(30),Vcg(31),Vcg(32),Vcg(33),Vcg(34),Vcg(35),Vcg(36),Vcg(37),Vcg(38),Vcg(39),
+        Vcg(40),Vcg(41),Vcg(42),Vcg(43),Vcg(44),Vcg(45),Vcg(46),Vcg(47),Vcg(48),Vcg(49),
+        Vcg(50),Vcg(51),Vcg(52),Vcg(53),Vcg(54),Vcg(55),Vcg(56),Vcg(57),Vcg(58),Vcg(59),
+        Vcg(60),Vcg(61),Vcg(62),Vcg(63),Vcg(64),Vcg(65),Vcg(66),Vcg(67),Vcg(68),Vcg(69),
+        Vcg(70),Vcg(71),Vcg(72),Vcg(73),Vcg(74),Vcg(75),Vcg(76),Vcg(77),Vcg(78),Vcg(79),
+        Vcg(80),Vcg(81),Vcg(82),Vcg(83),Vcg(84),Vcg(85),Vcg(86),Vcg(87),Vcg(88),Vcg(89),
+        Vcg(90),Vcg(91),Vcg(92),Vcg(93),Vcg(94),Vcg(95),Vcg(96),Vcg(97),Vcg(98),Vcg(99),
+        Vcg(100),Vcg(101),Vcg(102),Vcg(103),Vcg(104),Vcg(105),Vcg(106),Vcg(107),Vcg(108),Vcg(109),
+        Vcg(110),Vcg(111),Vcg(112),Vcg(113),Vcg(114),Vcg(115),Vcg(116),Vcg(117),Vcg(118),Vcg(119),
+        Vcg(120),Vcg(121),Vcg(122),Vcg(123),Vcg(124),Vcg(125),Vcg(126),Vcg(127),Vcg(128),Vcg(129),
+        Vcg(130),Vcg(131),Vcg(132),Vcg(133),Vcg(134),Vcg(135),Vcg(136),Vcg(137),Vcg(138),Vcg(139),
+        Vcg(140),Vcg(141),Vcg(142),Vcg(143),Vcg(144),Vcg(145),Vcg(146),Vcg(147),Vcg(148),Vcg(149),
+        Vcg(150),Vcg(151),Vcg(152),Vcg(153),Vcg(154),Vcg(155),Vcg(156),Vcg(157),Vcg(158),Vcg(159),
+        Vcg(160),Vcg(161),Vcg(162),Vcg(163),Vcg(164),Vcg(165),Vcg(166),Vcg(167),Vcg(168),Vcg(169),
+        Vcg(170),Vcg(171),Vcg(172),Vcg(173),Vcg(174),Vcg(175),Vcg(176),Vcg(177),Vcg(178),Vcg(179),
+        Vcg(180),Vcg(181),Vcg(182),Vcg(183),Vcg(184),Vcg(185),Vcg(186),Vcg(187),Vcg(188),Vcg(189),
+        Vcg(190),Vcg(191),Vcg(192),Vcg(193),Vcg(194),Vcg(195),Vcg(196),Vcg(197),Vcg(198),Vcg(199),
+        Vcg(200),Vcg(201),Vcg(202),Vcg(203),Vcg(204),Vcg(205),Vcg(206),Vcg(207),Vcg(208),Vcg(209),
+        Vcg(210),Vcg(211),Vcg(212),Vcg(213),Vcg(214),Vcg(215),Vcg(216),Vcg(217),Vcg(218),Vcg(219),
+        Vcg(220),Vcg(221),Vcg(222),Vcg(223),Vcg(224),Vcg(225),Vcg(226),Vcg(227),Vcg(228),Vcg(229),
+        Vcg(230),Vcg(231),Vcg(232),Vcg(233),Vcg(234),Vcg(235),Vcg(236),Vcg(237),Vcg(238),Vcg(239),
+        Vcg(240),Vcg(241),Vcg(242),Vcg(243),Vcg(244),Vcg(245),Vcg(246),Vcg(247),Vcg(248),Vcg(249),
+        Vcg(250),Vcg(251),Vcg(252),Vcg(253),Vcg(254),Vcg(255)};
+
+}
+#endif
+
diff --git a/common_video/vplib/main/source/interpolator.cc b/common_video/vplib/main/source/interpolator.cc
new file mode 100644
index 0000000..8e49eb1
--- /dev/null
+++ b/common_video/vplib/main/source/interpolator.cc
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+
+#include "interpolator.h"
+#include "scale_bilinear_yuv.h"
+
+namespace webrtc
+{
+
+interpolator::interpolator():
+_method(kBilinear),
+_srcWidth(0),
+_srcHeight(0),
+_dstWidth(0),
+_dstHeight(0)
+{
+}
+
+interpolator:: ~interpolator()
+{
+    //
+}
+
+WebRtc_Word32
+interpolator::Set(WebRtc_UWord32 srcWidth, WebRtc_UWord32 srcHeight,
+                  WebRtc_UWord32 dstWidth, WebRtc_UWord32 dstHeight,
+                  VideoType srcVideoType, VideoType dstVideoType,
+                  interpolatorType type)
+{
+    if (srcWidth < 1 || srcHeight < 1 || dstWidth < 1 || dstHeight < 1 )
+        return -1;
+
+    if (Method(type) < 0)
+        return -1;
+
+    if (!SupportedVideoType(srcVideoType, dstVideoType))
+        return -1;
+
+    _srcWidth = srcWidth;
+    _srcHeight = srcHeight;
+    _dstWidth = dstWidth;
+    _dstHeight = dstHeight;
+    return 0;
+}
+
+
+WebRtc_Word32
+interpolator::Interpolate(const WebRtc_UWord8* srcFrame,
+                          WebRtc_UWord8*& dstFrame)
+{
+    if (srcFrame == NULL)
+        return -1;
+
+    switch (_method)
+    {
+        case kBilinear :
+            return ScaleBilinear (srcFrame, dstFrame,
+                                  _srcWidth, _srcHeight,
+                                  _dstWidth, _dstHeight);
+        default :
+            return -1;
+    }
+}
+
+
+
+WebRtc_Word32
+interpolator::Method(interpolatorType type)
+{
+    _method = type;
+
+    return 0;
+}
+
+
+WebRtc_Word32
+interpolator::SupportedVideoType(VideoType srcVideoType,
+                                 VideoType dstVideoType)
+{
+    if (srcVideoType != dstVideoType)
+        return -1;
+
+    if ((srcVideoType != kI420) ||
+        (srcVideoType != kIYUV) ||
+        (srcVideoType != kYV12))
+        return -1;
+
+    return 0;
+}
+
+}  // namespace webrtc
diff --git a/common_video/vplib/main/source/scale_bilinear_yuv.cc b/common_video/vplib/main/source/scale_bilinear_yuv.cc
new file mode 100644
index 0000000..b92fb73
--- /dev/null
+++ b/common_video/vplib/main/source/scale_bilinear_yuv.cc
@@ -0,0 +1,343 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "scale_bilinear_yuv.h"
+#include <string.h>
+
+namespace webrtc
+{
+// 16.16 fixed point arithmetic
+const WebRtc_UWord32 kFractionBits = 16;
+const WebRtc_UWord32 kFractionMax = 1 << kFractionBits;
+const WebRtc_UWord32 kFractionMask = ((1 << kFractionBits) - 1);
+
+#if USE_MMX
+#if defined(_MSC_VER)
+#include <intrin.h>
+#else
+#include <mmintrin.h>
+#endif
+#endif
+
+#if USE_SSE2
+#include <emmintrin.h>
+#endif
+
+#if USE_SSE2
+// FilterHorizontal combines two rows of the image using linear interpolation.
+// SSE2 version does 16 pixels at a time
+
+static void FilterHorizontal(WebRtc_UWord8* ybuf,
+                             const WebRtc_UWord8* y0_ptr,
+                             const WebRtc_UWord8* y1_ptr,
+                             WebRtc_UWord32 source_width,
+                             WebRtc_UWord32 source_y_fraction)
+{
+    __m128i zero = _mm_setzero_si128();
+    __m128i y1_fraction = _mm_set1_epi16(source_y_fraction);
+    __m128i y0_fraction = _mm_set1_epi16(256 - source_y_fraction);
+
+    const __m128i* y0_ptr128 = reinterpret_cast<const __m128i*>(y0_ptr);
+    const __m128i* y1_ptr128 = reinterpret_cast<const __m128i*>(y1_ptr);
+    __m128i* dest128 = reinterpret_cast<__m128i*>(ybuf);
+    __m128i* end128 = reinterpret_cast<__m128i*>(ybuf + source_width);
+
+    do
+    {
+        __m128i y0 = _mm_loadu_si128(y0_ptr128);
+        __m128i y1 = _mm_loadu_si128(y1_ptr128);
+        __m128i y2 = _mm_unpackhi_epi8(y0, zero);
+        __m128i y3 = _mm_unpackhi_epi8(y1, zero);
+        y0 = _mm_unpacklo_epi8(y0, zero);
+        y1 = _mm_unpacklo_epi8(y1, zero);
+        y0 = _mm_mullo_epi16(y0, y0_fraction);
+        y1 = _mm_mullo_epi16(y1, y1_fraction);
+        y2 = _mm_mullo_epi16(y2, y0_fraction);
+        y3 = _mm_mullo_epi16(y3, y1_fraction);
+        y0 = _mm_add_epi16(y0, y1);
+        y2 = _mm_add_epi16(y2, y3);
+        y0 = _mm_srli_epi16(y0, 8);
+        y2 = _mm_srli_epi16(y2, 8);
+        y0 = _mm_packus_epi16(y0, y2);
+        *dest128++ = y0;
+        ++y0_ptr128;
+        ++y1_ptr128;
+    }
+    while (dest128 < end128);
+}
+#elif USE_MMX
+// MMX version does 8 pixels at a time
+static void FilterHorizontal(WebRtc_UWord8* ybuf,
+                             const WebRtc_UWord8* y0_ptr,
+                             const WebRtc_UWord8* y1_ptr,
+                             WebRtc_UWord32 source_width,
+                             WebRtc_UWord32 source_y_fraction)
+{
+    __m64 zero = _mm_setzero_si64();
+    __m64 y1_fraction = _mm_set1_pi16(source_y_fraction);
+    __m64 y0_fraction = _mm_set1_pi16(256 - source_y_fraction);
+
+    const __m64* y0_ptr64 = reinterpret_cast<const __m64*>(y0_ptr);
+    const __m64* y1_ptr64 = reinterpret_cast<const __m64*>(y1_ptr);
+    __m64* dest64 = reinterpret_cast<__m64*>(ybuf);
+    __m64* end64 = reinterpret_cast<__m64*>(ybuf + source_width);
+
+    do
+    {
+        __m64 y0 = *y0_ptr64++;
+        __m64 y1 = *y1_ptr64++;
+        __m64 y2 = _mm_unpackhi_pi8(y0, zero);
+        __m64 y3 = _mm_unpackhi_pi8(y1, zero);
+        y0 = _mm_unpacklo_pi8(y0, zero);
+        y1 = _mm_unpacklo_pi8(y1, zero);
+        y0 = _mm_mullo_pi16(y0, y0_fraction);
+        y1 = _mm_mullo_pi16(y1, y1_fraction);
+        y2 = _mm_mullo_pi16(y2, y0_fraction);
+        y3 = _mm_mullo_pi16(y3, y1_fraction);
+        y0 = _mm_add_pi16(y0, y1);
+        y2 = _mm_add_pi16(y2, y3);
+        y0 = _mm_srli_pi16(y0, 8);
+        y2 = _mm_srli_pi16(y2, 8);
+        y0 = _mm_packs_pu16(y0, y2);
+        *dest64++ = y0;
+    }
+    while (dest64 < end64);
+}
+#else  // no MMX or SSE2
+// C version does 8 at a time to mimic MMX code
+static void FilterHorizontal(WebRtc_UWord8* ybuf,
+                             const WebRtc_UWord8* y0_ptr,
+                             const WebRtc_UWord8* y1_ptr,
+                             WebRtc_UWord32 source_width,
+                             WebRtc_UWord32 source_y_fraction)
+{
+    WebRtc_UWord32 y1_fraction = source_y_fraction;
+    WebRtc_UWord32 y0_fraction = 256 - y1_fraction;
+    WebRtc_UWord8* end = ybuf + source_width;
+    do
+    {
+        ybuf[0] = (y0_ptr[0] * y0_fraction + y1_ptr[0] * y1_fraction) >> 8;
+        ybuf[1] = (y0_ptr[1] * y0_fraction + y1_ptr[1] * y1_fraction) >> 8;
+        ybuf[2] = (y0_ptr[2] * y0_fraction + y1_ptr[2] * y1_fraction) >> 8;
+        ybuf[3] = (y0_ptr[3] * y0_fraction + y1_ptr[3] * y1_fraction) >> 8;
+        ybuf[4] = (y0_ptr[4] * y0_fraction + y1_ptr[4] * y1_fraction) >> 8;
+        ybuf[5] = (y0_ptr[5] * y0_fraction + y1_ptr[5] * y1_fraction) >> 8;
+        ybuf[6] = (y0_ptr[6] * y0_fraction + y1_ptr[6] * y1_fraction) >> 8;
+        ybuf[7] = (y0_ptr[7] * y0_fraction + y1_ptr[7] * y1_fraction) >> 8;
+        y0_ptr += 8;
+        y1_ptr += 8;
+        ybuf += 8;
+    }
+    while (ybuf < end);
+}
+#endif
+
+static void FilterVertical(WebRtc_UWord8* ybuf,
+                           const WebRtc_UWord8* y0_ptr,
+                           WebRtc_UWord32 width,
+                           WebRtc_UWord32 source_dx)
+{
+    WebRtc_UWord32 x = 0;
+
+    for (WebRtc_UWord32 i = 0; i < width; i ++)
+    {
+        WebRtc_UWord32 y0 = y0_ptr[x >> 16];
+        WebRtc_UWord32 y1 = y0_ptr[(x >> 16) + 1];
+
+        WebRtc_UWord32 y_frac = (x & 65535);
+        ybuf[i] = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
+
+        x += source_dx;
+    }
+}
+
+
+WebRtc_Word32
+ScaleBilinear(const WebRtc_UWord8* srcFrame,
+              WebRtc_UWord8*& dstFrame,
+              WebRtc_UWord32 srcWidth,
+              WebRtc_UWord32 srcHeight,
+              WebRtc_UWord32 dstWidth,
+              WebRtc_UWord32 dstHeight)
+{
+    // Setting source
+    const WebRtc_UWord8* src = srcFrame;
+    WebRtc_UWord8* srcTmp = NULL;
+
+    const WebRtc_UWord32 srcStride = (srcWidth  + 15) & ~15;
+    const WebRtc_UWord32 srcUvStride = (((srcStride + 1 >> 1) + 15) & ~15);
+
+    const WebRtc_UWord32 srcStrideArray[3] = {srcStride,
+            srcUvStride,
+            srcUvStride
+                                             };
+    const WebRtc_UWord32 srcWidthArray[3] = {srcWidth,
+                                            (srcWidth + 1) >> 1,
+                                            (srcWidth + 1) >> 1
+                                            };
+
+    // if srcFrame isn't aligned to nice boundaries then copy it over
+    // int another buffer
+    if ((srcStride > srcWidth) || (srcUvStride > ((srcWidth + 1) >> 1)))
+    {
+        // allocate buffer that can accommodate the stride
+        srcTmp = new WebRtc_UWord8[srcStride*srcHeight*3 >> 1];
+        WebRtc_UWord8* tmpPlaneArray[3];
+        tmpPlaneArray[0] = srcTmp;
+        tmpPlaneArray[1] = tmpPlaneArray[0] + srcStride * srcHeight;
+        tmpPlaneArray[2] = tmpPlaneArray[1] + (srcStride >> 1)*(srcHeight >> 1);
+
+        WebRtc_UWord8* tmpPtr = srcTmp;
+        const WebRtc_UWord8* srcPtr = srcFrame;
+
+        for (WebRtc_UWord32 p = 0; p < 3; p++)
+        {
+            WebRtc_UWord8* dstPtr = tmpPlaneArray[p];
+            const WebRtc_UWord32 h = (p == 0) ? srcHeight : srcHeight >> 1;
+
+            for (WebRtc_UWord32 i = 0; i < h; i++)
+            {
+                memcpy(dstPtr, srcPtr, srcWidthArray[p]);
+                dstPtr += srcStrideArray[p];
+                srcPtr += srcWidthArray[p];
+            }
+        }
+        src = srcTmp;
+    }
+
+    const WebRtc_UWord8* srcPlaneArray[3];
+    srcPlaneArray[0] = src;
+    srcPlaneArray[1] = srcPlaneArray[0] + srcStride*srcHeight;
+    srcPlaneArray[2] = srcPlaneArray[1] + (srcStride >> 1)*(srcHeight >> 1);
+
+    // Setting destination
+    const WebRtc_UWord32 dstStride = (dstWidth + 31) & ~31;
+    const WebRtc_UWord32 dstUvStride = (((dstStride + 1 >> 1) + 31) & ~31);
+
+    if (dstFrame)
+    {
+        delete [] dstFrame;
+        dstFrame = NULL;
+    }
+
+    WebRtc_UWord32 dstRequiredSize = dstStride*dstHeight +
+                                     2*(dstUvStride*((dstHeight + 1) >> 1));
+    dstFrame = new WebRtc_UWord8[dstRequiredSize];
+    if (dstFrame == NULL)
+        return -1;
+
+    WebRtc_UWord8* dstPlaneArray[3] = {dstFrame,
+                                       dstPlaneArray[0] + dstStride*dstHeight,
+                                       dstPlaneArray[1] +
+                                       (dstUvStride*((dstHeight + 1) >> 1))
+                                      };
+
+    const WebRtc_UWord32 dstStrideArray[3] = {dstStride,
+            dstUvStride,
+            dstUvStride
+                                             };
+    const WebRtc_UWord32 dstWidthArray[3] = {dstWidth,
+                                            dstWidth>>1,
+                                            dstWidth>>1
+                                            };
+
+    for (WebRtc_UWord32 p = 0; p < 3; p++)
+    {
+        const WebRtc_UWord32 sh = (p == 0) ? srcHeight : srcHeight >> 1;
+        const WebRtc_UWord32 dh = (p == 0) ? dstHeight : dstHeight >> 1;
+        WebRtc_UWord8* filteredBuf = dstPlaneArray[p];
+        WebRtc_UWord8* horizontalFilteredBuf;
+        WebRtc_UWord8* intermediaryBuf = new WebRtc_UWord8[srcStrideArray[p]];
+
+        const WebRtc_UWord32 hscale_fixed = (sh << kFractionBits) / dh;
+        const WebRtc_UWord32 source_dx = srcWidthArray[p]*kFractionMax /
+                                         dstWidthArray[p];
+
+
+        for (WebRtc_UWord32 h = 0; h < dh; ++h)
+        {
+            horizontalFilteredBuf = filteredBuf;
+
+            if (source_dx != kFractionMax)
+                horizontalFilteredBuf = intermediaryBuf;
+
+            // horizontal filter
+            WebRtc_UWord32 source_h_subpixel = (h * hscale_fixed);
+            if (hscale_fixed >= (kFractionMax * 2))
+                // For 1/2 or less, center filter.
+                source_h_subpixel += kFractionMax / 2;
+
+            WebRtc_UWord32 source_h = source_h_subpixel >> kFractionBits;
+
+            const WebRtc_UWord8* ptr_0 = srcPlaneArray[p] +
+                                         source_h*srcStrideArray[p];
+
+            const WebRtc_UWord8* ptr_1 = ptr_0 + srcStrideArray[p];
+
+            // vertical scaler uses 16.8 fixed point
+            WebRtc_UWord32 source_h_fraction =
+                (source_h_subpixel & kFractionMask) >> 8;
+
+            if (hscale_fixed != kFractionMax &&
+                    source_h_fraction && ((source_h + 1) < sh))
+            {
+                FilterHorizontal(horizontalFilteredBuf, ptr_0, ptr_1,
+                                 srcWidthArray[p], source_h_fraction);
+            }
+            else
+            {
+                memcpy(horizontalFilteredBuf, ptr_1, srcWidthArray[p]);
+            }
+            filteredBuf[srcWidthArray[p]] = filteredBuf[srcWidthArray[p]-1];
+
+            // vertical filter only if necessary
+            if (source_dx != kFractionMax)
+                FilterVertical(filteredBuf, horizontalFilteredBuf,
+                               dstWidthArray[p], source_dx);
+
+            filteredBuf += dstStrideArray[p];
+        }
+
+        if (intermediaryBuf != NULL)
+            delete [] intermediaryBuf;
+    }
+
+    if (srcTmp != NULL)
+        delete [] srcTmp;
+
+    // Filtered image was placed in an aligned buffer.  If the
+    // final output is not in an aligned buffer copy the image over.
+    if (dstStride > dstWidth)
+    {
+        WebRtc_UWord8* dstFinal =
+            new WebRtc_UWord8[(dstWidth*dstHeight*3) >> 1];
+        WebRtc_UWord8* dstPtr = dstFinal;
+
+        for (WebRtc_UWord32 p = 0; p < 3; p++)
+        {
+            WebRtc_UWord8* srcPtr = dstPlaneArray[p];
+            const WebRtc_UWord32 h = (p == 0) ? dstHeight : dstHeight >> 1;
+
+            for (WebRtc_UWord32 i = 0; i < h; i++)
+            {
+                memcpy(dstPtr, srcPtr, dstWidthArray[p]);
+                dstPtr += dstWidthArray[p];
+                srcPtr += dstStrideArray[p];
+            }
+        }
+
+        delete [] dstFrame;
+        dstFrame = dstFinal;
+    }
+
+    return dstHeight;
+}
+
+}  // namespace webrtc
diff --git a/common_video/vplib/main/source/scale_bilinear_yuv.h b/common_video/vplib/main/source/scale_bilinear_yuv.h
new file mode 100644
index 0000000..08e905e
--- /dev/null
+++ b/common_video/vplib/main/source/scale_bilinear_yuv.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * scale_bilinear_yuv.h
+ * yuv bilinear scaler
+ */
+
+#ifndef WEBRTC_COMMON_VIDEO_INTERFACE_SCALE_BILINEAR_YUV_H
+#define WEBRTC_COMMON_VIDEO_INTERFACE_SCALE_BILINEAR_YUV_H
+
+#include "typedefs.h"
+#include "vplib.h"
+
+namespace webrtc
+{
+
+WebRtc_Word32 ScaleBilinear(const WebRtc_UWord8* src, WebRtc_UWord8*& dst,
+                            WebRtc_UWord32 sW, WebRtc_UWord32 sH,
+                            WebRtc_UWord32 dW, WebRtc_UWord32 dH);
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_COMMON_VIDEO_INTERFACE_SCALE_BILINEAR_YUV_H
diff --git a/common_video/vplib/main/source/vplib.cc b/common_video/vplib/main/source/vplib.cc
new file mode 100644
index 0000000..804a159
--- /dev/null
+++ b/common_video/vplib/main/source/vplib.cc
@@ -0,0 +1,4438 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vplib.h"
+
+#include <string.h>     // memcpy(), memset()
+#include <assert.h>
+#include <stdlib.h>     // abs
+
+//#define SCALEOPT //Currently for windows only. June 2010
+
+#ifdef SCALEOPT
+#include <emmintrin.h>
+#endif
+
+// webrtc includes
+#include "conversion_tables.h"
+
+namespace webrtc
+{
+
+//Verify and allocate buffer
+static WebRtc_Word32 VerifyAndAllocate(WebRtc_UWord8*& buffer, WebRtc_UWord32 currentSize,
+                                       WebRtc_UWord32 newSize);
+// clip value to [0,255]
+inline WebRtc_UWord8 Clip(WebRtc_Word32 val);
+
+#ifdef SCALEOPT
+void *memcpy_16(void * dest, const void * src, size_t n);
+void *memcpy_8(void * dest, const void * src, size_t n);
+#endif
+
+
+WebRtc_UWord32
+CalcBufferSize(VideoType type, WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    WebRtc_UWord32 bitsPerPixel = 32;
+    switch(type)
+    {
+        case kI420:
+            bitsPerPixel = 12;
+            break;
+        case kNV12:
+            bitsPerPixel = 12;
+            break;
+        case kNV21:
+            bitsPerPixel = 12;
+            break;
+        case kIYUV:
+            bitsPerPixel = 12;
+            break;
+        case kYV12:
+            bitsPerPixel = 12;
+            break;
+        case kRGB24:
+            bitsPerPixel = 24;
+            break;
+        case kARGB:
+            bitsPerPixel = 32;
+            break;
+        case kARGB4444:
+            bitsPerPixel = 16;
+            break;
+        case kRGB565:
+            bitsPerPixel = 16;
+            break;
+        case kARGB1555:
+            bitsPerPixel = 16;
+            break;
+        case kYUY2:
+            bitsPerPixel = 16;
+            break;
+        case kUYVY:
+            bitsPerPixel = 16;
+            break;
+        default:
+            assert(false);
+            break;
+    }
+    return (width * height * bitsPerPixel) >> 3; // bytes
+}
+
+WebRtc_UWord32
+CalcBufferSize(VideoType incomingVideoType, VideoType convertedVideoType,
+               WebRtc_UWord32 length)
+{
+    WebRtc_UWord32 incomingBitsPerPixel = 32;
+    switch(incomingVideoType)
+    {
+        case kI420:
+            incomingBitsPerPixel = 12;
+            break;
+        case kNV12:
+            incomingBitsPerPixel = 12;
+            break;
+        case kNV21:
+            incomingBitsPerPixel = 12;
+            break;
+        case kIYUV:
+            incomingBitsPerPixel = 12;
+            break;
+        case kYV12:
+            incomingBitsPerPixel = 12;
+            break;
+        case kRGB24:
+            incomingBitsPerPixel = 24;
+            break;
+        case kARGB:
+            incomingBitsPerPixel = 32;
+            break;
+        case kARGB4444:
+            incomingBitsPerPixel = 16;
+            break;
+        case kRGB565:
+            incomingBitsPerPixel = 16;
+            break;
+        case kARGB1555:
+            incomingBitsPerPixel = 16;
+            break;
+        case kYUY2:
+            incomingBitsPerPixel = 16;
+            break;
+        case kUYVY:
+            incomingBitsPerPixel = 16;
+            break;
+        default:
+            assert(false);
+            break;
+    }
+
+    WebRtc_Word32 convertedBitsPerPixel = 32;
+    switch(convertedVideoType)
+    {
+        case kI420:
+            convertedBitsPerPixel = 12;
+            break;
+        case kIYUV:
+            convertedBitsPerPixel = 12;
+            break;
+        case kYV12:
+            convertedBitsPerPixel = 12;
+            break;
+        case kRGB24:
+            convertedBitsPerPixel = 24;
+            break;
+        case kARGB:
+            convertedBitsPerPixel = 32;
+            break;
+        case kARGB4444:
+            convertedBitsPerPixel = 16;
+            break;
+        case kRGB565:
+            convertedBitsPerPixel = 16;
+            break;
+        case kARGB1555:
+            convertedBitsPerPixel = 16;
+            break;
+        case kYUY2:
+            convertedBitsPerPixel = 16;
+            break;
+        case kUYVY:
+            convertedBitsPerPixel = 16;
+            break;
+        default:
+            assert(false);
+            break;
+    }
+    return (length * convertedBitsPerPixel) / incomingBitsPerPixel;
+}
+
+WebRtc_Word32
+ConvertI420ToRGB24(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                   WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // RGB orientation - bottom up
+    WebRtc_UWord8* out = outFrame + width * height * 3 - width * 3;
+    WebRtc_UWord8* out2 = out - width * 3;
+    WebRtc_UWord32 h, w;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1, *y2 ,*u, *v;
+    y1 = inFrame;
+    y2 = y1 + width;
+    u =  y1 + width * height;
+    v =  u + ((width * height) >> 2);
+    for (h = (height >> 1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {// vertical and horizontal sub-sampling
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] +                mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]]                + 128) >> 8);
+            out[2] = Clip(tmpR);
+            out[1] = Clip(tmpG);
+            out[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] +                mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]]                + 128) >> 8);
+            out2[2] = Clip(tmpR);
+            out2[1] = Clip(tmpG);
+            out2[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] +                mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]]                + 128) >> 8);
+            out[5] = Clip(tmpR);
+            out[4] = Clip(tmpG);
+            out[3] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] +                mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] +                128) >> 8);
+            out2[5] = Clip(tmpR);
+            out2[4] = Clip(tmpG);
+            out2[3] = Clip(tmpB);
+
+            out  += 6;
+            out2 += 6;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out -= width * 9;
+        out2 -= width * 9;
+    } // end height for
+
+    return width * height * 3;
+}
+
+WebRtc_Word32
+ConvertI420ToARGB(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+    }
+    WebRtc_Word32 diff = strideOut - width;
+    WebRtc_UWord8* out1 = outFrame;
+    WebRtc_UWord8* out2 = out1 + strideOut * 4;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + (( width * height ) >> 2 );
+    WebRtc_UWord32 h, w;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+
+    for (h = (height >> 1); h > 0; h--)
+    {
+        //do 2 rows at the time
+        for (w = 0; w < (width >> 1); w++)
+        {   // vertical and horizontal sub-sampling
+
+            tmpR = (WebRtc_UWord32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_UWord32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] +128) >> 8);
+            tmpB = (WebRtc_UWord32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8);
+            out1[3] = 0xff;
+            out1[2] = Clip(tmpR);
+            out1[1] = Clip(tmpG);
+            out1[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_UWord32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_UWord32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_UWord32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[3] = 0xff;
+            out2[2] = Clip(tmpR);
+            out2[1] = Clip(tmpG);
+            out2[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_UWord32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_UWord32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_UWord32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out1[7] = 0xff;
+            out1[6] = Clip(tmpR);
+            out1[5] = Clip(tmpG);
+            out1[4] = Clip(tmpB);
+
+            tmpR = (WebRtc_UWord32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_UWord32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_UWord32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[7] = 0xff;
+            out2[6] = Clip(tmpR);
+            out2[5] = Clip(tmpG);
+            out2[4] = Clip(tmpB);
+
+            out1 += 8;
+            out2 += 8;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out1 += (strideOut + diff) * 4;
+        out2 += (strideOut + diff) * 4;
+
+    } // end height for
+    return strideOut * height * 4;
+}
+
+WebRtc_Word32
+ConvertI420ToRGBAMac(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                     WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (height < 1 || width < 1)
+    {
+        return -1;
+    }
+
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    } else if (strideOut  < width)
+    {
+        return -1;
+    }
+    WebRtc_Word32 diff = strideOut - width;
+
+    WebRtc_UWord8 * out = outFrame;
+    WebRtc_UWord8 * out2 = out + strideOut * 4;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    WebRtc_Word32 tmpG, tmpB, tmpR;
+    WebRtc_UWord32 h, w;
+    y1 = inFrame;
+    y2 = y1 + width;
+    v = y1 + width * height;
+    u = v + ((width * height) >> 2);
+
+    for (h = (height >> 1); h > 0; h--)
+    {
+        //do 2 rows at the time
+        for (w = 0; w < (width >> 1); w++)
+        {
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128  ) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128 ) >> 8);
+            out[1] = Clip(tmpR);
+            out[2] = Clip(tmpG);
+            out[3] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[1] = Clip(tmpR);
+            out2[2] = Clip(tmpG);
+            out2[3] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[5] = Clip(tmpR);
+            out[6] = Clip(tmpG);
+            out[7] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[5] = Clip(tmpR);
+            out2[6] = Clip(tmpG);
+            out2[7] = Clip(tmpB);
+
+            out[0] = 0xff;
+            out[4] = 0xff;
+            out += 8;
+            out2[0] = 0xff;
+            out2[4] = 0xff;
+            out2 += 8;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+
+        y1 += width;
+        y2 += width;
+        out += (width + diff * 2) * 4;
+        out2 += (width + diff * 2) * 4;
+    }
+    return strideOut * height * 4;
+}
+
+// Little Endian...
+WebRtc_Word32
+ConvertI420ToARGB4444(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                      WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    } else if (strideOut < width)
+    {
+        return -1;
+    }
+    // RGB orientation - bottom up
+    WebRtc_UWord8* out = outFrame + strideOut * (height - 1) * 2;
+    WebRtc_UWord8* out2 = out - 2 * strideOut;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + ((width * height) >> 2);
+    WebRtc_UWord32 h, w;
+
+    for (h = (height >> 1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {   // vertical and horizontal sub-sampling
+            // Convert to RGB888 and re-scale to 4 bits
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8);
+            out[0] =(WebRtc_UWord8)((Clip(tmpG) & 0xf0) + (Clip(tmpB) >> 4));
+            out[1] = (WebRtc_UWord8)(0xf0 + (Clip(tmpR) >> 4));
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[0] = (WebRtc_UWord8)((Clip(tmpG) & 0xf0 ) + (Clip(tmpB) >> 4));
+            out2[1] = (WebRtc_UWord8) (0xf0 + (Clip(tmpR) >> 4));
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[2] = (WebRtc_UWord8)((Clip(tmpG) & 0xf0 ) + (Clip(tmpB) >> 4));
+            out[3] = (WebRtc_UWord8)(0xf0 + (Clip(tmpR) >> 4));
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[2] = (WebRtc_UWord8)((Clip(tmpG) & 0xf0 ) + (Clip(tmpB) >> 4));
+            out2[3] = (WebRtc_UWord8)(0xf0 + (Clip(tmpR) >> 4));
+
+            out  += 4;
+            out2 += 4;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out -= (2 * strideOut + width) * 2;
+        out2 -= (2 * strideOut + width) * 2;
+     } // end height for
+
+    return strideOut * height * 2;
+}
+
+WebRtc_Word32
+ConvertI420ToRGB565(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                    WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord16* out = (WebRtc_UWord16*)(outFrame) + width * (height - 1);
+    WebRtc_UWord16* out2 = out - width ;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + (width * height >> 2);
+    WebRtc_UWord32 h, w;
+
+    for (h = (height >>1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {   // vertical and horizontal sub-sampling
+            // 1. Convert to RGB888
+            // 2. Shift to adequate location (in the 16 bit word) - RGB 565
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8);
+            out[0]  = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[0] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                       + (Clip(tmpB ) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            y1 += 2;
+            y2 += 2;
+            out += 2;
+            out2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out -= 3 * width;
+        out2 -=  3 * width;
+    } // end height for
+
+    return width * height * 2;
+}
+
+
+//Same as ConvertI420ToRGB565 but doesn't flip vertically.
+WebRtc_Word32
+ConvertI420ToRGB565Android(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                           WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord16* out = (WebRtc_UWord16*)(outFrame);
+    WebRtc_UWord16* out2 = out +  (width) ;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    WebRtc_UWord32 h, w;
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + (width * height >> 2);
+
+    for (h = (height >>1); h > 0; h--)
+    {
+      // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {
+            // vertical and horizontal sub-sampling
+            // 1. Convert to RGB888
+            // 2. Shift to adequate location (in the 16 bit word) - RGB 565
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8);
+            out[0]  = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[0] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                       + (Clip(tmpB ) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3)
+                                        + (Clip(tmpB) >> 3);
+
+            y1 += 2;
+            y2 += 2;
+            out += 2;
+            out2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out += width;
+        out2 +=  width;
+    } // end height for
+
+    return width * height * 2;
+}
+
+WebRtc_Word32
+ConvertI420ToARGB1555(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                      WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord16* out = (WebRtc_UWord16*)(outFrame) + width * (height - 1);
+    WebRtc_UWord16* out2 = out - width ;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    WebRtc_UWord32 h, w;
+
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + (width * height >> 2);
+
+    for (h = (height >> 1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {
+            // vertical and horizontal sub-sampling
+            // 1. Convert to RGB888
+            // 2. shift to adequate location (in the 16 bit word) - RGB 555
+            // 3. Add 1 for alpha value
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8);
+            out[0]  = (WebRtc_UWord16)(0x8000 + ((Clip(tmpR) & 0xf8) << 10) + ((Clip(tmpG) & 0xf8) << 3)
+                                       + (Clip(tmpB) >> 3));
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[0]  = (WebRtc_UWord16)(0x8000 + ((Clip(tmpR) & 0xf8) << 10) + ((Clip(tmpG) & 0xf8) << 3)
+                                        + (Clip(tmpB) >> 3));
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[1]  = (WebRtc_UWord16)(0x8000 + ((Clip(tmpR) & 0xf8) << 10) + ((Clip(tmpG) & 0xf8) << 3)
+                                       + (Clip(tmpB) >> 3));
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[1]  = (WebRtc_UWord16)(0x8000 + ((Clip(tmpR) & 0xf8) << 10) + ((Clip(tmpG) & 0xf8) << 3)
+                                        + (Clip(tmpB) >> 3));
+
+            y1 += 2;
+            y2 += 2;
+            out += 2;
+            out2 += 2;
+            u++;
+            v++;
+        }
+        y1 += width;
+        y2 += width;
+        out -= 3 * width;
+        out2 -=  3 * width;
+    } // end height for
+    return strideOut * height * 2;
+}
+
+WebRtc_Word32
+ConvertI420ToYUY2(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if(strideOut == 0)
+    {
+      strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+     }
+
+    const WebRtc_UWord8* in1 = inFrame;
+    const WebRtc_UWord8* in2 = inFrame + width ;
+    const WebRtc_UWord8* inU = inFrame + width * height;
+    const WebRtc_UWord8* inV = inU + width * (height >> 2);
+
+    WebRtc_UWord8* out1 = outFrame;
+    WebRtc_UWord8* out2 = outFrame + 2*strideOut;
+
+    //YUY2 - Macro-pixel = 2 image pixels
+    //Y0U0Y1V0....Y2U2Y3V2...Y4U4Y5V4....
+
+#ifndef SCALEOPT
+    for (WebRtc_UWord32 i = 0; i < (height >> 1);i++)
+    {
+        for (WebRtc_UWord32 j = 0; j < (width >> 1);j++)
+        {
+            out1[0] = in1[0];
+            out1[1] = *inU;
+            out1[2] = in1[1];
+            out1[3] = *inV;
+
+            out2[0] = in2[0];
+            out2[1] = *inU;
+            out2[2] = in2[1];
+            out2[3] = *inV;
+            out1 += 4;
+            out2 += 4;
+            inU++;
+            inV++;
+            in1 += 2;
+            in2 += 2;
+        }
+        in1 += width;
+        in2 += width;
+        out1 += 2 * strideOut + 2 * (strideOut - width);
+        out2 += 2 * strideOut + 2 * (strideOut - width);
+    }
+#else
+    for (WebRtc_UWord32 i = 0; i < (height >> 1);i++)
+    {
+        WebRtc_Word32 width__ = (width >> 4);
+        _asm
+        {
+            ;pusha
+            mov       eax, DWORD PTR [in1]                       ;1939.33
+            mov       ecx, DWORD PTR [in2]                       ;1939.33
+            mov       ebx, DWORD PTR [inU]                       ;1939.33
+            mov       edx, DWORD PTR [inV]                       ;1939.33
+            loop0:
+            movq      xmm6, QWORD PTR [ebx]          ;inU
+            movq      xmm0, QWORD PTR [edx]          ;inV
+            punpcklbw xmm6, xmm0                     ;inU, inV mix
+            ;movdqa    xmm1, xmm6
+            ;movdqa    xmm2, xmm6
+            ;movdqa    xmm4, xmm6
+
+            movdqu    xmm3, XMMWORD PTR [eax]        ;in1
+            movdqa    xmm1, xmm3
+            punpcklbw xmm1, xmm6                     ;in1, inU, in1, inV
+            mov       esi, DWORD PTR [out1]
+            movdqu    XMMWORD PTR [esi], xmm1        ;write to out1
+
+            movdqu    xmm5, XMMWORD PTR [ecx]        ;in2
+            movdqa    xmm2, xmm5
+            punpcklbw xmm2, xmm6                     ;in2, inU, in2, inV
+            mov       edi, DWORD PTR [out2]
+            movdqu    XMMWORD PTR [edi], xmm2        ;write to out2
+
+            punpckhbw xmm3, xmm6                     ;in1, inU, in1, inV again
+            movdqu    XMMWORD PTR [esi+16], xmm3     ;write to out1 again
+            add       esi, 32
+            mov       DWORD PTR [out1], esi
+
+            punpckhbw xmm5, xmm6                     ;inU, in2, inV again
+            movdqu    XMMWORD PTR [edi+16], xmm5     ;write to out2 again
+            add       edi, 32
+            mov       DWORD PTR [out2], edi
+
+            add       ebx, 8
+            add       edx, 8
+            add       eax, 16
+            add       ecx, 16
+
+            mov       esi, DWORD PTR [width__]
+            sub       esi, 1
+            mov       DWORD PTR [width__], esi
+            jg        loop0
+
+            mov       DWORD PTR [in1], eax                       ;1939.33
+            mov       DWORD PTR [in2], ecx                       ;1939.33
+            mov       DWORD PTR [inU], ebx                       ;1939.33
+            mov       DWORD PTR [inV], edx                       ;1939.33
+
+            ;popa
+            emms
+        }
+        in1 += width;
+        in2 += width;
+        out1 += 2 * strideOut + 2 * (strideOut - width);
+        out2 += 2 * strideOut + 2 * (strideOut - width);
+    }
+#endif
+    return strideOut * height * 2;
+}
+
+WebRtc_Word32
+ConvertI420ToUYVY(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+         return -1;
+    }
+    if(strideOut == 0)
+    {
+        strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 i = 0;
+    const WebRtc_UWord8* in1 = inFrame;
+    const WebRtc_UWord8* in2 = inFrame + width ;
+    const WebRtc_UWord8* inU = inFrame + width * height;
+    const WebRtc_UWord8* inV = inFrame + width * height + width * (height >> 2);
+
+    WebRtc_UWord8* out1 = outFrame;
+    WebRtc_UWord8* out2 = outFrame + 2 * strideOut;
+
+    //Macro-pixel = 2 image pixels
+    //U0Y0V0Y1....U2Y2V2Y3...U4Y4V4Y5.....
+
+#ifndef SCALEOPT
+    for (; i < (height >> 1);i++)
+    {
+        for (WebRtc_UWord32 j = 0; j < (width >> 1) ;j++)
+        {
+            out1[0] = *inU;
+            out1[1] = in1[0];
+            out1[2] = *inV;
+            out1[3] = in1[1];
+
+            out2[0] = *inU;
+            out2[1] = in2[0];
+            out2[2] = *inV;
+            out2[3] = in2[1];
+            out1 += 4;
+            out2 += 4;
+            inU++;
+            inV++;
+            in1 += 2;
+            in2 += 2;
+        }
+        in1 += width;
+        in2 += width;
+        out1 += 2 * (strideOut + (strideOut - width));
+        out2 += 2 * (strideOut + (strideOut - width));
+    }
+#else
+    for (; i< (height >> 1);i++)
+    {
+        WebRtc_Word32 width__ = (width >> 4);
+        _asm
+        {
+            ;pusha
+            mov       eax, DWORD PTR [in1]                       ;1939.33
+            mov       ecx, DWORD PTR [in2]                       ;1939.33
+            mov       ebx, DWORD PTR [inU]                       ;1939.33
+            mov       edx, DWORD PTR [inV]                       ;1939.33
+loop0:
+            movq      xmm6, QWORD PTR [ebx]          ;inU
+            movq      xmm0, QWORD PTR [edx]          ;inV
+            punpcklbw xmm6, xmm0                     ;inU, inV mix
+            movdqa    xmm1, xmm6
+            movdqa    xmm2, xmm6
+            movdqa    xmm4, xmm6
+
+            movdqu    xmm3, XMMWORD PTR [eax]        ;in1
+            punpcklbw xmm1, xmm3                     ;inU, in1, inV
+            mov       esi, DWORD PTR [out1]
+            movdqu    XMMWORD PTR [esi], xmm1        ;write to out1
+
+            movdqu    xmm5, XMMWORD PTR [ecx]        ;in2
+            punpcklbw xmm2, xmm5                     ;inU, in2, inV
+            mov       edi, DWORD PTR [out2]
+            movdqu    XMMWORD PTR [edi], xmm2        ;write to out2
+
+            punpckhbw xmm4, xmm3                     ;inU, in1, inV again
+            movdqu    XMMWORD PTR [esi+16], xmm4     ;write to out1 again
+            add       esi, 32
+            mov       DWORD PTR [out1], esi
+
+            punpckhbw xmm6, xmm5                     ;inU, in2, inV again
+            movdqu    XMMWORD PTR [edi+16], xmm6     ;write to out2 again
+            add       edi, 32
+            mov       DWORD PTR [out2], edi
+
+            add       ebx, 8
+            add       edx, 8
+            add       eax, 16
+            add       ecx, 16
+
+            mov       esi, DWORD PTR [width__]
+            sub       esi, 1
+            mov       DWORD PTR [width__], esi
+            jg        loop0
+
+            mov       DWORD PTR [in1], eax                       ;1939.33
+            mov       DWORD PTR [in2], ecx                       ;1939.33
+            mov       DWORD PTR [inU], ebx                       ;1939.33
+            mov       DWORD PTR [inV], edx                       ;1939.33
+
+            ;popa
+            emms
+        }
+        in1 += width;
+        in2 += width;
+        out1 += 2 * (strideOut + (strideOut - width));
+        out2 += 2 * (strideOut + (strideOut - width));
+    }
+#endif
+    return strideOut * height * 2;
+}
+
+WebRtc_Word32
+ConvertI420ToYV12(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (height < 1 || width < 1 )
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+    }
+
+    // copy Y
+    for (WebRtc_UWord32 i = 0; i < height; i++)
+    {
+#ifndef SCALEOPT
+        memcpy(outFrame, inFrame, width);
+#else
+        memcpy_16(outFrame, inFrame, width);
+#endif
+        inFrame += width;
+        outFrame += strideOut;
+    }
+    // copy U
+    outFrame += (strideOut >> 1) * height >> 1;
+    for (WebRtc_UWord32 i = 0; i < height >>1; i++)
+    {
+#ifndef SCALEOPT
+        memcpy(outFrame, inFrame, width >> 1);
+#else
+        memcpy_8(outFrame, inFrame, width >> 1);
+#endif
+        inFrame += width >> 1;
+        outFrame += strideOut >> 1;
+    }
+    outFrame -= strideOut*height >> 1;
+    // copy V
+    for (WebRtc_UWord32 i = 0; i < height >> 1; i++)
+    {
+#ifndef SCALEOPT
+        memcpy(outFrame, inFrame, width >> 1);
+#else
+        memcpy_8(outFrame, inFrame, width >> 1);
+#endif
+        inFrame += width >> 1;
+        outFrame += strideOut >> 1;
+    }
+    return ((3 * strideOut * height) >> 1);
+}
+
+WebRtc_Word32
+ConvertYV12ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 width, WebRtc_UWord32 height,
+                  WebRtc_UWord8* outFrame)
+{
+    if (height < 1 || width <1)
+    {
+        return -1;
+    }
+    WebRtc_UWord8 *u, *v, *uo, *vo;
+    WebRtc_Word32 lumlen = 0;
+    WebRtc_Word32 crlen = 0;
+
+    lumlen = height * width;
+    crlen = (lumlen >> 2);
+    v = (WebRtc_UWord8 *)inFrame + lumlen;
+    uo = outFrame + lumlen;
+    u = v + crlen;
+    vo = uo + crlen;
+
+    memcpy(outFrame, inFrame, lumlen); // copy luminance
+    memcpy(vo, v, crlen);   // copy V to V out
+    memcpy(uo, u, crlen);   // copy U to U out
+
+    return (width * height * 3) >> 1;
+}
+
+WebRtc_Word32
+ConvertNV12ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // Bi-Planar: Y plane followed by an interlaced U and V plane
+    WebRtc_UWord8* out = outFrame;
+    // copying Y plane as is
+    memcpy(out, inFrame, width * height);
+    // de-interlacing U and V
+    const WebRtc_UWord8 *interlacedSrc;
+    WebRtc_UWord8 *u, *v;
+    u = outFrame + width * height;
+    v = u + (width * height >> 2);
+    interlacedSrc = inFrame + width * height;
+    for (WebRtc_UWord32 ind = 0; ind < (width * height >> 2); ind ++)
+    {
+        u[ind] = interlacedSrc[2 * ind];
+        v[ind] = interlacedSrc[2 * ind + 1];
+    }
+    return (width * height * 3 >> 1);
+}
+WebRtc_Word32
+ConvertNV12ToI420AndRotate180(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                              WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // Bi-Planar: Y plane followed by an interlaced U and V plane
+    WebRtc_UWord8* out = outFrame;
+
+    for(WebRtc_UWord32 index = 0; index < width * height; index++)
+    {
+        out[index] = inFrame[width * height - index - 1];
+    }
+    // de-interlacing U and V
+    const WebRtc_UWord8 *interlacedSrc;
+    WebRtc_UWord8 *u, *v;
+    u = outFrame + width * height;
+    v = u + (width * height >> 2);
+    interlacedSrc = inFrame + width * height;
+    // extracting and rotating 180
+    for (WebRtc_UWord32 index = 0; index < (width * height >> 2); index++)
+    {
+        u[(width * height >> 2) - index - 1] = interlacedSrc[2 * index];
+        v[(width * height >> 2) - index - 1] = interlacedSrc[2 * index + 1];
+    }
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertNV12ToI420AndRotateClockwise(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord8* targetBuffer = outFrame;
+    const WebRtc_UWord8* sourcePtr = inFrame;
+    const WebRtc_UWord8* interlacedSrc = inFrame + width * height;
+
+    WebRtc_UWord32 index = 0;
+
+    // Rotate Y
+    for(WebRtc_UWord32 newRow = 0; newRow < width; ++newRow)
+    {
+        for(WebRtc_Word32 newColumn = height-1; newColumn >= 0; --newColumn)
+        {
+            targetBuffer[index++] = sourcePtr[newColumn * width + newRow];
+        }
+    }
+
+    // extracting and rotating U and V
+    WebRtc_UWord8* u  = targetBuffer + width * height;
+    WebRtc_UWord8* v  = u + (width * height >> 2);
+    for (WebRtc_UWord32 colInd = 0; colInd < height >> 1; colInd ++)
+    {
+        for (WebRtc_UWord32 rowInd = 0; rowInd < width >> 1; rowInd ++)
+        {
+            u[rowInd * height / 2 + colInd] = interlacedSrc[(height / 2 - colInd - 1) * width
+                                                             + 2 * rowInd];
+            v[rowInd * height / 2 + colInd] = interlacedSrc[(height / 2 - colInd - 1) * width
+                                                             + 2 * rowInd + 1];
+        }
+    }
+
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertNV12ToI420AndRotateAntiClockwise(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                        WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord8* targetBuffer = outFrame;
+    const WebRtc_UWord8* sourcePtr = inFrame;
+    const WebRtc_UWord8* interlacedSrc = inFrame + width * height;
+
+    WebRtc_UWord32 index = 0;
+    // Rotate Y
+    for(WebRtc_Word32 newRow = width - 1; newRow >= 0; --newRow)
+    {
+        for(WebRtc_UWord32 newColumn = 0; newColumn < height; ++newColumn)
+        {
+            targetBuffer[index++] = sourcePtr[newColumn * width + newRow];
+        }
+    }
+
+    // extracting and rotating U and V
+    WebRtc_UWord8* u  = targetBuffer + width * height;
+    WebRtc_UWord8* v  = u + (width * height >> 2);
+    index = 0;
+    for(WebRtc_Word32 newRow = (width >> 1) - 1; newRow >= 0; --newRow)
+    {
+        for(WebRtc_UWord32 newColumn = 0; newColumn < (height >> 1); ++newColumn)
+        {
+            u[index] = interlacedSrc[2 * (newColumn * (width >> 1) + newRow)];
+            v[index] = interlacedSrc[2 * (newColumn * (width >> 1) + newRow) + 1];
+            index++;
+        }
+    }
+
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertNV12ToRGB565(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                    WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // Bi-Planar: Y plane followed by an interlaced U and V plane
+    const WebRtc_UWord8* interlacedSrc = inFrame + width * height;
+    WebRtc_UWord16* out = (WebRtc_UWord16*)(outFrame) + width * (height - 1);
+    WebRtc_UWord16* out2 = out - width;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2;
+    y1 = inFrame;
+    y2 = y1 + width;
+    WebRtc_UWord32 h, w;
+
+    for (h = (height >> 1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {   // vertical and horizontal sub-sampling
+            // 1. Convert to RGB888
+            // 2. Shift to adequate location (in the 16 bit word) - RGB 565
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[interlacedSrc[1]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[interlacedSrc[0]]
+                                    + mapVcg[interlacedSrc[1]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[interlacedSrc[0]] + 128) >> 8);
+            out[0]  = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3) + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[interlacedSrc[1]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[interlacedSrc[0]]
+                                    + mapVcg[interlacedSrc[1]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[interlacedSrc[0]] + 128) >> 8);
+            out2[0] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3) + (Clip(tmpB) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[interlacedSrc[1]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[interlacedSrc[0]]
+                                    + mapVcg[interlacedSrc[1]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[interlacedSrc[0]] + 128) >> 8);
+            out[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3) + (Clip(tmpB ) >> 3);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[interlacedSrc[1]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[interlacedSrc[0]]
+                                    + mapVcg[interlacedSrc[1]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[interlacedSrc[0]] + 128) >> 8);
+            out2[1] = (WebRtc_UWord16)((Clip(tmpR) & 0xf8) << 8) + ((Clip(tmpG) & 0xfc) << 3) + (Clip(tmpB) >> 3);
+
+            y1 += 2;
+            y2 += 2;
+            out += 2;
+            out2 += 2;
+            interlacedSrc += 2;
+            }
+        y1 += width;
+        y2 += width;
+        out -= 3 * width;
+        out2 -= 3 * width;
+    } // end height for
+
+    return (width * height * 2);
+}
+
+//NV21 Android Functions
+WebRtc_Word32
+ConvertNV21ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // Bi-Planar: Y plane followed by an interlaced U and V plane
+    WebRtc_UWord8* out = outFrame;
+    // copying Y plane as is
+    memcpy(out, inFrame, width * height);
+    // de-interlacing U and V
+    const WebRtc_UWord8 *interlacedSrc;
+    WebRtc_UWord8 *u, *v;
+    u = outFrame + width * height;
+    v = u + (width * height >> 2);
+    interlacedSrc = inFrame + width * height;
+    for (WebRtc_UWord32 ind = 0; ind < (width * height >> 2); ind ++)
+    {
+        v[ind] = interlacedSrc[2 * ind];
+        u[ind] = interlacedSrc[2 * ind + 1];
+    }
+    return (width * height * 3 >> 1);
+}
+WebRtc_Word32
+ConvertNV21ToI420AndRotate180(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                              WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    // Bi-Planar: Y plane followed by an interlaced U and V plane
+    WebRtc_UWord8* out = outFrame;
+    for(WebRtc_UWord32 index = 0; index < width * height; index++)
+    {
+        out[index] = inFrame[width * height - index - 1];
+    }
+    // de-interlacing U and V
+    const WebRtc_UWord8 *interlacedSrc;
+    WebRtc_UWord8 *u, *v;
+    u = outFrame + width * height;
+    v = u + (width * height >> 2);
+    interlacedSrc = inFrame + width * height;
+    // extracting and rotating 180
+    for (WebRtc_UWord32 index = 0; index < (width * height >> 2); index++)
+    {
+        v[(width * height >> 2) - index - 1] = interlacedSrc[2 * index];
+        u[(width * height >> 2) - index - 1] = interlacedSrc[2 * index + 1];
+    }
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertNV21ToI420AndRotateClockwise(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                    WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    // Paint the destination buffer black
+    memset(outFrame,0,width * height);
+    memset(outFrame + width * height,127,(width * height) / 2);
+    const WebRtc_Word32 offset = (width - height) / 2;
+
+    //Y
+    WebRtc_UWord8* yn= outFrame;
+    const WebRtc_UWord8* ys= inFrame;
+    for (WebRtc_UWord32 m = 0; m < height; ++m)// New row
+    {
+        yn += offset;
+        for (WebRtc_UWord32 n = 0; n < height; ++n) // new column
+        {
+            (*yn++) = ys[(height - 1 - n) * width + offset + m];
+        }
+        yn += offset;
+    }
+
+    //U & V
+    WebRtc_UWord8* un= outFrame + height * width;
+    WebRtc_UWord8* vn= outFrame+height * width + height * width / 4;
+    const WebRtc_UWord8* uvs= inFrame + height * width;
+
+    for (WebRtc_UWord32 m = 0;m < height / 2; ++m)// New row
+    {
+        un += offset / 2;
+        vn += offset / 2;
+        for (WebRtc_UWord32 n = 0;n < height / 2; ++n) // new column
+        {
+            (*un++) = uvs[(height / 2 - 1 - n) * width + offset + 2 * m + 1];
+            (*vn++) = uvs[(height / 2 - 1 - n) * width + offset + 2 * m];
+        }
+        un += offset / 2;
+        vn += offset / 2;
+    }
+
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertNV21ToI420AndRotateAntiClockwise(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                                        WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    // Paint the destination buffer black
+    memset(outFrame,0,width * height);
+    memset(outFrame + width * height, 127, (width * height) / 2);
+
+    const WebRtc_Word32 offset = (width - height) / 2;
+
+    //Y
+    WebRtc_UWord8* yn = outFrame;
+    const WebRtc_UWord8* ys = inFrame;
+    for (WebRtc_UWord32 m = 0;m < height; ++m)// New row
+    {
+        yn += offset;
+        for (WebRtc_UWord32 n = 0;n < height; ++n) // new column
+        {
+            (*yn++) = ys[width * (n + 1) - 1 - offset - m];
+        }
+        yn += offset;
+    }
+
+    //U & V
+    WebRtc_UWord8* un= outFrame + height * width;
+    WebRtc_UWord8* vn= outFrame + height * width + height * width / 4;
+    const WebRtc_UWord8* uvs= inFrame + height * width;
+
+    for (WebRtc_UWord32 m = 0;m < height / 2; ++m)// New row
+    {
+        un += offset / 2;
+        vn += offset / 2;
+        for (WebRtc_UWord32 n = 0;n < height / 2; ++n) // new column
+        {
+            (*un++) = uvs[width * (n + 1) - 1 - offset - 2 * m];;
+            (*vn++) = uvs[width * (n + 1) - 1 - offset - 2 * m - 1];;
+        }
+        un += offset / 2;
+        vn += offset / 2;
+    }
+    return (width * height * 3 >> 1);
+}
+
+WebRtc_Word32
+ConvertI420ToRGBAIPhone(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                        WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    } else if (strideOut < width)
+    {
+        return -1;
+    }
+
+    // RGB orientation - bottom up
+    // same as ARGB but reverting RGB <-> BGR (same as previous version)
+    WebRtc_UWord8* out = outFrame + strideOut * height * 4 - strideOut * 4;
+    WebRtc_UWord8* out2 = out - strideOut * 4;
+    WebRtc_Word32 tmpR, tmpG, tmpB;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    WebRtc_UWord32 h, w;
+
+    y1 = inFrame;
+    y2 = y1 + width;
+    u = y1 + width * height;
+    v = u + ((width * height) >> 2);
+
+    for (h = (height >> 1); h > 0; h--)
+    {  // 2 rows at a time, 2 y's at a time
+        for (w = 0; w < (width >> 1); w++)
+        {   // vertical and horizontal sub-sampling
+            tmpR = (WebRtc_Word32)((298 * (y1[0] - 16) + 409 * (v[0] - 128) + 128) >> 8);
+            tmpG = (WebRtc_Word32)((298 * (y1[0] - 16) - 100 * (u[0] - 128)
+                                    - 208 * (v[0] - 128) + 128 ) >> 8);
+            tmpB = (WebRtc_Word32)((298 * (y1[0] - 16) + 516 * (u[0] - 128) + 128 ) >> 8);
+
+            out[3] = 0xff;
+            out[0] = Clip(tmpR);
+            out[1] = Clip(tmpG);
+            out[2] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((298 * (y2[0] - 16) + 409 * (v[0] - 128) + 128) >> 8);
+            tmpG = (WebRtc_Word32)((298 * (y2[0] - 16) - 100 * (u[0] - 128)
+                                    - 208 * (v[0] - 128) + 128) >> 8);
+            tmpB = (WebRtc_Word32)((298 * (y2[0] - 16) + 516 * (u[0] - 128) + 128) >> 8);
+
+            out2[3] = 0xff;
+            out2[0] = Clip(tmpR);
+            out2[1] = Clip(tmpG);
+            out2[2] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((298 * (y1[1] - 16) + 409 * (v[0] - 128) + 128 ) >> 8);
+            tmpG = (WebRtc_Word32)((298 * (y1[1] - 16) - 100 * (u[0] - 128)
+                                    - 208 * (v[0] - 128) + 128 ) >> 8);
+            tmpB = (WebRtc_Word32)((298 * (y1[1] - 16) + 516 * (u[0] - 128) + 128) >> 8);
+
+            out[7] = 0xff;
+            out[4] = Clip(tmpR);
+            out[5] = Clip(tmpG);
+            out[6] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((298 * (y2[1] - 16) + 409 * (v[0] - 128) + 128) >> 8);
+            tmpG = (WebRtc_Word32)((298 * (y2[1] - 16) - 100 * (u[0] - 128)
+                                    - 208 * (v[0] - 128) + 128) >> 8);
+            tmpB = (WebRtc_Word32)((298 * (y2[1] - 16) + 516 * (u[0] - 128) + 128 ) >> 8);
+
+            out2[7] = 0xff;
+            out2[4] = Clip(tmpR);
+            out2[5] = Clip(tmpG);
+            out2[6] = Clip(tmpB);
+
+            out  += 8;
+            out2 += 8;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+
+        y1 += width;
+        y2 += width;
+        out -= (2 * strideOut + width) * 4;
+        out2 -= (2 * strideOut + width) * 4;
+    } // end height for
+
+    return strideOut * height * 4;
+}
+
+WebRtc_Word32
+ConvertI420ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (strideOut == 0 || strideOut == width)
+    {
+        memcpy(outFrame, inFrame, 3 * width * (height >> 1));
+        strideOut = width;
+    } else if (strideOut < width)
+    {
+        return -1;
+    } else
+    {
+        WebRtc_UWord32 i = 0;
+        for (; i < height; i++)
+        {
+            memcpy(outFrame,inFrame ,width);
+            outFrame += strideOut;
+            inFrame += width;
+        }
+        for (i = 0; i < (height >> 1);i++)
+        {
+            memcpy(outFrame, inFrame,width >> 1);
+            outFrame += strideOut >> 1;
+            inFrame += width >> 1;
+        }
+        for (i = 0; i< (height >> 1); i++)
+        {
+            memcpy(outFrame, inFrame,width >> 1);
+            outFrame += strideOut >> 1;
+            inFrame += width >> 1;
+        }
+    }
+    return 3 * strideOut * (height >> 1);
+}
+
+WebRtc_Word32
+ConvertUYVYToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth, WebRtc_UWord32 inHeight,
+                  WebRtc_UWord8* outFrame, WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || inHeight < 1 || outHeight < 1 || outWidth < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 i = 0;
+    WebRtc_UWord32 j = 0;
+    WebRtc_Word32 cutDiff = 0; // in pixels
+    WebRtc_Word32 padDiffLow = 0; // in pixels
+    WebRtc_Word32 padDiffHigh = 0; // in pixels
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + outWidth * outHeight;
+    WebRtc_UWord8* outCb = outFrame + outWidth * outHeight + outWidth * (outHeight >> 2);
+
+    // cut height?
+    if (inHeight > outHeight)
+    {
+        // parse away half of the lines
+      inFrame += ((inHeight - outHeight) / 2) * inWidth * 2;
+    }
+    // cut width?
+    if (inWidth > outWidth)
+    {
+        cutDiff = (inWidth - outWidth); // in pixels
+        // start half of the width diff into the line
+        inFrame += cutDiff; // each pixel is 2 bytes hence diff is the correct value in bytes
+    }
+    // pad height?
+    if (inHeight < outHeight)
+    {
+        // pad top
+        WebRtc_Word32 diff = (outHeight - inHeight) >> 1;
+        memset(outI, 0, diff * outWidth);
+        outI += diff * outWidth;
+        WebRtc_Word32 colorLength = (diff >> 1) * (outWidth >> 1);
+        memset(outCr, 127, colorLength);
+        memset(outCb, 127, colorLength);
+        outCr += colorLength;
+        outCb += colorLength;
+
+        // pad bottom
+        memset(outI + outWidth * inHeight, 0, diff * outWidth);
+        memset(outCr + (outWidth * inHeight >> 2), 127, colorLength);
+        memset(outCb + (outWidth * inHeight >> 2), 127, colorLength);
+    }
+    // pad width?
+    if (inWidth < outWidth)
+    {
+        padDiffLow = (outWidth - inWidth) >> 1; // in pixels
+        padDiffHigh = (outWidth - inWidth) - padDiffLow; // in pixels
+    }
+    WebRtc_UWord32 height = 0;
+    if (inHeight > outHeight)
+        height = outHeight;
+    else
+        height = inHeight;
+
+    for (; i< (height >> 1); i++) // 2 rows per loop
+    {
+        // pad beginning of row?
+        if (padDiffLow)
+        {
+            // pad row
+            memset(outI,0,padDiffLow);
+            memset(outCr,127,padDiffLow >> 1);
+            memset(outCb,127,padDiffLow >> 1);
+            outI += padDiffLow;
+            outCr += padDiffLow >> 1;
+            outCb += padDiffLow >> 1;
+        }
+
+        for (j = 0; j < (inWidth >> 1); j++) // 2 pixels per loop
+        {
+            outI[0] = inFrame[1];
+            *outCr = inFrame[0];
+            outI[1] = inFrame[3];
+            *outCb = inFrame[2];
+            inFrame += 4;
+            outI += 2;
+            outCr++;
+            outCb++;
+        }
+        // pad end of row?
+        if (padDiffHigh)
+        {
+            memset(outI,0,padDiffHigh);
+            memset(outCr,127,padDiffHigh >> 1);
+            memset(outCb,127,padDiffHigh >> 1);
+            outI += padDiffHigh;
+            outCr += padDiffHigh >> 1;
+            outCb += padDiffHigh >> 1;
+        }
+        // next row
+        // pad beginning of row?
+        memset(outI,0,padDiffLow);
+        outI += padDiffLow;
+
+        for (j = 0; j < (inWidth >> 1);j++)
+        {
+            outI[0] = inFrame[1];
+            outI[1] = inFrame[3];
+            inFrame += 4;
+            outI += 2;
+        }
+        // pad end of row?
+        if (padDiffHigh)
+        {
+            memset(outI,0,padDiffHigh);
+            outI += padDiffHigh;
+        } else
+        {
+            // cut row
+            for (j = 0; j < (outWidth >> 1); j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[1];
+                *outCr = inFrame[0];
+                outI[1] = inFrame[3];
+                *outCb = inFrame[2];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            inFrame += cutDiff * 2;
+            // next row
+            for (j = 0; j < (outWidth >> 1);j++)
+            {
+                outI[0] = inFrame[1];
+                outI[1] = inFrame[3];
+                inFrame += 4;
+                outI += 2;
+            }
+            inFrame += cutDiff * 2;
+        }
+    }
+    return outWidth * (outHeight >> 1) * 3;
+}
+
+WebRtc_Word32
+ConvertUYVYToI420interlaced(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                            WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                            WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || inHeight < 1 || outHeight < 1 || outWidth < 1)
+    {
+        return -1;
+    }
+    WebRtc_Word32 i = 0;
+    WebRtc_UWord32 j = 0;
+    WebRtc_Word32 cutDiff = 0; // in pixels
+    WebRtc_Word32 padDiffLow = 0; // in pixels
+    WebRtc_Word32 padDiffHigh = 0; // in pixels
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + outWidth * outHeight;
+    WebRtc_UWord8* outCb = outFrame + outWidth * outHeight + outWidth * ( outHeight >> 2 );
+
+    // cut height?
+    if (inHeight > outHeight)
+    {
+        // parse away half of the lines
+        inFrame += (( inHeight - outHeight ) / 2) * inWidth * 2;
+    }
+    // cut width?
+    if (inWidth > outWidth)
+    {
+        cutDiff = (inWidth - outWidth); // in pixels
+        // start half of the width diff into the line
+        inFrame += cutDiff; // each pixel is 2 bytes hence diff is the correct value in bytes
+    }
+    // pad height?
+    if (inHeight < outHeight)
+    {
+        // pad top
+        WebRtc_Word32 diff = (outHeight - inHeight) >> 1;
+        memset(outI, 0, diff * outWidth);
+        outI += diff * outWidth;
+        WebRtc_Word32 colorLength =(diff >> 1) * (outWidth >> 1);
+        memset(outCr, 127, colorLength);
+        memset(outCb, 127, colorLength);
+        outCr += colorLength;
+        outCb += colorLength;
+
+        // pad bottom
+        memset(outI+outWidth * inHeight, 0, diff * outWidth);
+        memset(outCr+(outWidth * inHeight >> 2), 127, colorLength);
+        memset(outCb+(outWidth * inHeight >> 2), 127, colorLength);
+    }
+    // pad width?
+    if (inWidth < outWidth)
+    {
+        padDiffLow = (outWidth - inWidth) >> 1; // in pixels
+        padDiffHigh = (outWidth - inWidth) - padDiffLow; // in pixels
+    }
+    WebRtc_Word32 height = 0;
+    if (inHeight > outHeight)
+        height = outHeight;
+    else
+        height = inHeight;
+
+    for (; i < (height >> 1); i++) // 2 rows per loop
+    {
+        // pad beginning of row?
+        if (padDiffLow)
+        {
+            // pad row
+            memset(outI,0,padDiffLow);
+            memset(outCr,127,padDiffLow >> 1);
+            memset(outCb,127,padDiffLow >> 1);
+            outI += padDiffLow;
+            outCr += padDiffLow / 2;
+            outCb += padDiffLow / 2;
+
+            for (j = 0; j < (inWidth >> 1); j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[1];
+                *outCr = inFrame[0];
+                outI[1] = inFrame[3];
+                *outCb = inFrame[2];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                memset(outCr,127,padDiffHigh >> 1);
+                memset(outCb,127,padDiffHigh >> 1);
+                outI += padDiffHigh;
+                outCr += padDiffHigh >> 1;
+                outCb += padDiffHigh >> 1;
+            }
+            // next row
+            // pad beginning of row?
+            memset(outI,0,padDiffLow);
+            outI += padDiffLow;
+
+            for (j = 0; j < (inWidth >> 1); j++)
+            {
+                outI[0] = inFrame[1];
+                outI[1] = inFrame[3];
+                inFrame += 4;
+                outI += 2;
+            }
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                outI += padDiffHigh;
+            }
+        } else
+        {
+            // cut row
+            for (j = 0; j < (outWidth >> 1); j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[1];
+                *outCr = inFrame[0];
+                outI[1] = inFrame[3];
+                *outCb = inFrame[2];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            inFrame -= (outWidth * 2);
+            const WebRtc_UWord8 *inFrame2 = inFrame + (inWidth * 2) * 2;
+
+            if(i + 1 == (height >> 1))
+            {
+                // last row
+                for (j = 0; j < (outWidth >> 1); j++)
+                {
+                    // copy last row
+                    outI[0] = inFrame[1];
+                    outI[1] = inFrame[3];
+                    inFrame += 4;
+                    inFrame2 += 4;
+                    outI += 2;
+                }
+            } else
+            {
+                // next row
+                for (j = 0; j < (outWidth >> 1); j++)
+                {
+                    outI[0] = (inFrame[1] + inFrame2[1]) >> 1;
+                    outI[1] = (inFrame[3] + inFrame2[1]) >> 1;
+                    inFrame += 4;
+                    inFrame2 += 4;
+                    outI += 2;
+                }
+            }
+            inFrame += cutDiff * 2;
+            inFrame += inWidth * 2; // skip next row
+        }
+    }
+    return outWidth * (outHeight >> 1) * 3;
+}
+
+WebRtc_Word32
+ConvertUYVYToI420(WebRtc_UWord32 width,WebRtc_UWord32 height, const WebRtc_UWord8* inFrame,
+                  WebRtc_UWord8* outFrame)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 i = 0;
+    WebRtc_UWord32 j = 0;
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + width * height;
+    WebRtc_UWord8* outCb = outFrame + width * height + width * (height >> 2);
+    for (; i< (height >> 1);i++)
+    {
+        for (j = 0; j < (width >> 1); j++)
+        {
+            outI[0] = inFrame[1];
+            *outCr = inFrame[0];
+            outI[1] = inFrame[3];
+            *outCb = inFrame[2];
+            inFrame += 4;
+            outI += 2;
+            outCr++;
+            outCb++;
+        }
+        for (j = 0; j < (width >> 1); j++)
+        {
+            outI[0] = inFrame[1];
+            outI[1] = inFrame[3];
+            inFrame += 4;
+            outI += 2;
+        }
+    }
+    return width * (height >> 1) * 3;
+}
+
+WebRtc_Word32
+ConvertYUY2ToI420interlaced(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                            WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame,
+                            WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || inHeight < 1 || outHeight < 1 || outWidth < 1)
+    {
+        return -1;
+    }
+    // use every other row and interpolate the removed row
+    WebRtc_UWord32 i = 0;
+    WebRtc_UWord32 j = 0;
+    WebRtc_Word32 cutDiff = 0; // in pixels
+    WebRtc_Word32 padDiffLow = 0; // in pixels
+    WebRtc_Word32 padDiffHigh = 0; // in pixels
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* inPtr3 = (WebRtc_UWord8*)inFrame + inWidth * 2 * 2; // ptr to third row
+    WebRtc_UWord8* outCr = outFrame + outWidth * outHeight;
+    WebRtc_UWord8* outCb = outFrame +outWidth * outHeight + outWidth * (outHeight >> 2);
+
+    // cut height?
+    if(inHeight > outHeight)
+    {
+        // parse away half of the lines
+        inFrame += ((inHeight - outHeight) / 2) * inWidth * 2;
+        inPtr3 += ((inHeight - outHeight) / 2) * inWidth * 2;
+    }
+    // cut width?
+    if(inWidth > outWidth)
+    {
+        cutDiff = (inWidth - outWidth); // in pixels
+        // start half of the width diff into the line
+        inPtr3 += cutDiff;
+        inFrame += cutDiff; // each pixel is 2 bytes hence diff is the correct value in bytes
+    }
+    // pad height?
+    if(inHeight < outHeight)
+    {
+        // pad top
+        WebRtc_Word32 diff = (outHeight - inHeight) / 2;
+        memset(outI, 0, diff * outWidth);
+        outI += diff * outWidth;
+        WebRtc_Word32 colorLength =(diff / 2) * (outWidth / 2);
+        memset(outCr, 127, colorLength);
+        memset(outCb, 127, colorLength);
+        outCr+= colorLength;
+        outCb+= colorLength;
+
+        // pad bottom
+        memset(outI + outWidth * inHeight, 0, diff * outWidth);
+        memset(outCr + (outWidth * inHeight / 4), 127, colorLength);
+        memset(outCb + (outWidth * inHeight / 4), 127, colorLength);
+    }
+    // pad width?
+    if(inWidth < outWidth)
+    {
+        padDiffLow = (outWidth - inWidth) / 2; // in pixels
+        padDiffHigh = (outWidth - inWidth) - padDiffLow; // in pixels
+    }
+    WebRtc_UWord32 height = 0;
+    if(inHeight > outHeight)
+        height = outHeight;
+    else
+        height = inHeight;
+
+    for (; i< (height >> 1);i++) // 2 rows per loop
+    {
+        // pad beginning of row?
+        if(padDiffLow)
+        {
+            // pad row
+            memset(outI,0,padDiffLow);
+            memset(outCr,127,padDiffLow / 2);
+            memset(outCb,127,padDiffLow / 2);
+            outI += padDiffLow;
+            outCr += padDiffLow / 2;
+            outCb += padDiffLow / 2;
+
+            for (j = 0; j< (inWidth >> 1);j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[0];
+                *outCr = inFrame[1];
+                outI[1] = inFrame[2];
+                *outCb = inFrame[3];
+                inFrame +=4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                memset(outCr,127,padDiffHigh / 2);
+                memset(outCb,127,padDiffHigh / 2);
+                outI += padDiffHigh;
+                outCr += padDiffHigh / 2;
+                outCb += padDiffHigh / 2;
+            }
+            // next row
+            // pad beginning of row?
+            memset(outI,0,padDiffLow);
+            outI += padDiffLow;
+            inFrame -= inWidth * 2;
+            if (i == (height >> 1) - 1)
+            {
+                // last loop
+                // copy the last row
+                for (j = 0; j< (inWidth >> 1); j++)
+                {
+                    outI[0] = inFrame[0];
+                    outI[1] = inFrame[2];
+                    inFrame += 4;
+                    outI += 2;
+                }
+            } else
+            {
+                // turn back inFrame
+                for (j = 0; j < (inWidth >> 1); j++)
+                {
+                    outI[0] = (inFrame[0] + inPtr3[0]) >> 1;
+                    outI[1] = (inFrame[2] + inPtr3[2]) >> 1;
+                    inFrame += 4;
+                    inPtr3 += 4;
+                    outI += 2;
+                }
+                inFrame += inWidth * 2;
+                inPtr3 += inWidth * 2;
+            }
+
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                outI += padDiffHigh;
+            }
+        } else
+        {
+            // cut row
+            for (j = 0; j < (outWidth >> 1); j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[0];
+                *outCr = inFrame[1];
+                outI[1] = inFrame[2];
+                *outCb = inFrame[3];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            inFrame += cutDiff * 2;
+            inFrame -= inWidth * 2;
+
+            if (i == (height >> 1) -1)
+            {
+                // last loop
+                // copy the last row
+                for (j = 0; j < (outWidth >> 1);j++)
+                {
+                    outI[0] = inFrame[0];
+                    outI[1] = inFrame[2];
+                    inFrame +=4;
+                    outI += 2;
+                }
+            } else
+            {
+                // next row
+                for (j = 0; j< (outWidth >> 1);j++)
+                {
+                    outI[0] = (inFrame[0] + inPtr3[0]) >> 1;
+                    outI[1] = (inFrame[2] + inPtr3[2]) >> 1;
+                    inPtr3 += 4;
+                    inFrame += 4;
+                    outI += 2;
+                }
+                inFrame += cutDiff * 2;
+                inPtr3 += cutDiff * 2;
+            }
+            inFrame += inWidth * 2;
+            inPtr3 += inWidth * 2;
+        }
+    }
+    return outWidth * (outHeight >> 1) * 3;
+}
+
+WebRtc_Word32
+ConvertYUY2ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth, WebRtc_UWord32 inHeight,
+                  WebRtc_UWord8* outFrame, WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || inHeight < 1 || outHeight < 1 || outWidth < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 i = 0;
+    WebRtc_UWord32 j = 0;
+    WebRtc_Word32 cutDiff = 0; // in pixels
+    WebRtc_Word32 padDiffLow = 0; // in pixels
+    WebRtc_Word32 padDiffHigh = 0; // in pixels
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + outWidth * outHeight;
+    WebRtc_UWord8* outCb = outFrame + outWidth * outHeight + outWidth * (outHeight >> 2);
+
+    // cut height?
+    if (inHeight > outHeight)
+    {
+        // parse away half of the lines
+        inFrame += ((inHeight - outHeight) >> 1) * inWidth * 2;
+    }
+    // cut width?
+    if (inWidth > outWidth)
+    {
+        cutDiff = (inWidth - outWidth); // in pixels
+        // start half of the width diff into the line
+        inFrame += cutDiff; // each pixel is 2 bytes hence diff is the correct value in bytes
+    }
+    // pad height?
+    if (inHeight < outHeight)
+    {
+        // pad top
+        WebRtc_Word32 diff = (outHeight - inHeight) >> 1;
+        memset(outI, 0, diff * outWidth);
+        outI += diff * outWidth;
+        WebRtc_Word32 colorLength =(diff >> 1) * (outWidth >> 1);
+        memset(outCr, 127, colorLength);
+        memset(outCb, 127, colorLength);
+        outCr += colorLength;
+        outCb += colorLength;
+
+        // pad bottom
+        memset(outI + outWidth * inHeight, 0, diff * outWidth);
+        memset(outCr + (outWidth * inHeight >> 2), 127, colorLength);
+        memset(outCb + (outWidth * inHeight >> 2), 127, colorLength);
+    }
+    // pad width?
+    if (inWidth < outWidth)
+    {
+        padDiffLow = (outWidth - inWidth) >> 1; // in pixels
+        padDiffHigh = (outWidth - inWidth) - padDiffLow; // in pixels
+    }
+    WebRtc_UWord32 height = 0;
+    if (inHeight > outHeight)
+        height = outHeight;
+    else
+        height = inHeight;
+
+    for (; i< (height >> 1); i++) // 2 rows per loop
+    {
+        // pad beginning of row?
+        if (padDiffLow)
+        {
+            // pad row
+            memset(outI,0,padDiffLow);
+            memset(outCr,127,padDiffLow >> 1);
+            memset(outCb,127,padDiffLow >> 1);
+            outI += padDiffLow;
+            outCr += padDiffLow >> 1;
+            outCb += padDiffLow >> 1;
+
+            for (j = 0; j< (inWidth >> 1);j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[0];
+                *outCr = inFrame[1];
+                outI[1] = inFrame[2];
+                *outCb = inFrame[3];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                memset(outCr,127,padDiffHigh >> 1);
+                memset(outCb,127,padDiffHigh >> 1);
+                outI += padDiffHigh;
+                outCr += padDiffHigh >> 1;
+                outCb += padDiffHigh >> 1;
+            }
+            // next row
+            // pad beginning of row?
+            memset(outI,0,padDiffLow);
+            outI += padDiffLow;
+
+            for (j = 0; j< (inWidth >> 1); j++)
+            {
+                outI[0] = inFrame[0];
+                outI[1] = inFrame[2];
+                inFrame += 4;
+                outI += 2;
+            }
+            // pad end of row?
+            if (padDiffHigh)
+            {
+                memset(outI,0,padDiffHigh);
+                outI += padDiffHigh;
+            }
+        } else
+        {
+            // cut row
+            for (j = 0; j < (outWidth >> 1); j++) // 2 pixels per loop
+            {
+                outI[0] = inFrame[0];
+                *outCr = inFrame[1];
+                outI[1] = inFrame[2];
+                *outCb = inFrame[3];
+                inFrame += 4;
+                outI += 2;
+                outCr++;
+                outCb++;
+            }
+            inFrame += cutDiff * 2;
+            // next row
+            for (j = 0; j < (outWidth >> 1); j++)
+            {
+                outI[0] = inFrame[0];
+                outI[1] = inFrame[2];
+                inFrame += 4;
+                outI += 2;
+            }
+            inFrame += cutDiff * 2;
+        }
+    }
+    return outWidth * (outHeight >> 1) * 3;
+}
+
+WebRtc_Word32
+ConvertYUY2ToI420(WebRtc_UWord32 width, WebRtc_UWord32 height,const WebRtc_UWord8* inFrame,
+                  WebRtc_UWord8* outFrame)
+{
+#ifndef SCALEOPT
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 i =0;
+    WebRtc_UWord32 j =0;
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + width * height;
+    WebRtc_UWord8* outCb = outFrame +width * height + width * (height >> 2);
+
+    for (; i < (height >> 1); i++)
+    {
+        for (j = 0; j < (width >> 1); j++)
+        {
+            outI[0] = inFrame[0];
+            *outCr = inFrame[1];
+            outI[1] = inFrame[2];
+            *outCb = inFrame[3];
+            inFrame += 4;
+            outI += 2;
+            outCr++;
+            outCb++;
+        }
+        for (j = 0; j < (width >> 1); j++)
+        {
+            outI[0] = inFrame[0];
+            outI[1] = inFrame[2];
+            inFrame += 4;
+            outI += 2;
+        }
+    }
+#else
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_Word32 i =0;
+    WebRtc_Word32 j =0;
+    WebRtc_UWord8* outI = outFrame;
+    WebRtc_UWord8* outCr = outFrame + width * height;
+    WebRtc_UWord8* outCb = outFrame + width * height + width * (height >> 2);
+
+    WebRtc_Word32 height_half = height / 2;
+
+    _asm{
+    mov       esi, DWORD PTR [width]
+    mov       edx, DWORD PTR [height_half]
+
+    ; prepare masks:
+    pxor      xmm0, xmm0
+    pcmpeqd   xmm1, xmm1
+    punpcklbw xmm1, xmm0
+    pcmpeqd   xmm2, xmm2
+    punpcklbw xmm0, xmm2
+    test      edx, edx
+    jle       exit_
+
+    xor       ebx, ebx
+    mov       edi, DWORD PTR [outFrame]
+    sar       esi, 4
+    test      esi, esi
+    jle       exit_
+
+    loop0:
+    add       ebx, 1
+
+    mov       DWORD PTR [i], ebx
+    mov       ebx, DWORD PTR [inFrame]
+    mov       edx, DWORD PTR [outCr]
+    mov       eax, DWORD PTR [outCb]
+    xor       ecx, ecx
+
+    loop1:
+
+    movdqa    xmm5, xmm1
+
+    movdqa    xmm2, xmm1
+    movdqu    xmm4, XMMWORD PTR [ebx]
+    movdqu    xmm3, XMMWORD PTR [ebx+16]
+
+    add       ebx, 32
+    pand      xmm5, xmm4
+    pand      xmm4, xmm0
+    psrldq    xmm4, 1
+    pand      xmm2, xmm3
+    pand      xmm3, xmm0
+    psrldq    xmm3, 1
+
+    packuswb  xmm5, xmm2
+
+    movdqu    XMMWORD PTR [edi], xmm5
+    movdqa    xmm2, xmm1
+    packuswb  xmm4, xmm3
+    pand      xmm2, xmm4
+    pand      xmm4, xmm0
+    psrldq    xmm4, 1
+    packuswb  xmm2, xmm4
+
+    movq      QWORD PTR [edx], xmm2
+    psrldq    xmm2, 8
+    movq      QWORD PTR [eax], xmm2
+
+    add       edi, 16
+    add       edx, 8
+    add       eax, 8
+    add       ecx, 1
+    cmp       ecx, esi
+    jl        loop1
+
+    mov       DWORD PTR [outCb], eax
+    mov       DWORD PTR [outCr], edx
+    mov       edx, DWORD PTR [height_half]
+    mov       DWORD PTR [inFrame], ebx
+    mov       ebx, DWORD PTR [i]
+
+    test      esi, esi
+    jle       exit_
+
+    mov       eax, DWORD PTR [inFrame] //now becomes 00568FE8
+    xor       ecx, ecx
+
+    loop2:
+
+    movdqu    xmm3, XMMWORD PTR [eax]
+    movdqu    xmm2, XMMWORD PTR [eax+16]
+    add       eax, 32
+    pand      xmm3, xmm1
+    pand      xmm2, xmm1
+    packuswb  xmm3, xmm2
+    movdqu    XMMWORD PTR [edi], xmm3
+
+    add       edi, 16
+    add       ecx, 1
+    cmp       ecx, esi
+    jl        loop2
+
+    mov       DWORD PTR [inFrame], eax //now 005692A8
+    mov       eax, DWORD PTR [width]
+    cmp       ebx, edx
+    jl        loop0
+    exit_:
+    }
+#endif
+    return width * (height >> 1) * 3;
+}
+
+// make a center cut
+WebRtc_Word32
+CutI420Frame(WebRtc_UWord8* frame, WebRtc_UWord32 fromWidth, WebRtc_UWord32 fromHeight,
+             WebRtc_UWord32 toWidth, WebRtc_UWord32 toHeight)
+{
+    if (toWidth < 1 || fromWidth < 1 || toHeight < 1 || fromHeight < 1 )
+    {
+        return -1;
+    }
+    if (toWidth == fromWidth && toHeight == fromHeight)
+    {
+        // nothing to do
+      return 3 * toHeight * toWidth / 2;
+    }
+    if (toWidth > fromWidth || toHeight > fromHeight)
+    {
+        // error
+        return -1;
+    }
+    WebRtc_UWord32 i = 0;
+    WebRtc_Word32 m = 0;
+    WebRtc_UWord32 loop = 0;
+    WebRtc_UWord32 halfToWidth = toWidth / 2;
+    WebRtc_UWord32 halfToHeight = toHeight / 2;
+    WebRtc_UWord32 halfFromWidth = fromWidth / 2;
+    WebRtc_UWord32 halfFromHeight= fromHeight / 2;
+    WebRtc_UWord32 cutHeight = ( fromHeight - toHeight ) / 2; //12
+    WebRtc_UWord32 cutWidth = ( fromWidth - toWidth ) / 2; // 16
+
+    for (i = fromWidth * cutHeight + cutWidth; loop < toHeight ; loop++, i += fromWidth)
+    {
+        memcpy(&frame[m],&frame[i],toWidth);
+        m += toWidth;
+    }
+    i = fromWidth * fromHeight; // ilum
+    loop = 0;
+    for ( i += (halfFromWidth * cutHeight / 2 + cutWidth / 2);
+          loop < halfToHeight; loop++,i += halfFromWidth)
+    {
+        memcpy(&frame[m],&frame[i],halfToWidth);
+        m += halfToWidth;
+    }
+    loop = 0;
+    i = fromWidth * fromHeight + halfFromHeight * halfFromWidth; // ilum +Cr
+    for( i += (halfFromWidth * cutHeight / 2 + cutWidth / 2); loop < halfToHeight; loop++, i += halfFromWidth)
+    {
+        memcpy(&frame[m],&frame[i],halfToWidth);
+        m += halfToWidth;
+    }
+    return halfToWidth * toHeight * 3;// new size  64*96*3; // 128/2 == 64
+}
+
+WebRtc_Word32
+ConvertI420ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth,
+                  WebRtc_UWord32 inHeight, WebRtc_UWord8* outFrame, WebRtc_UWord32 outWidth,
+                  WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || outWidth < 1 || inHeight < 1 || outHeight < 1 )
+    {
+        return -1;
+    }
+    if (inWidth == outWidth && inHeight == outHeight)
+    {
+        memcpy(outFrame, inFrame, 3*outWidth*(outHeight>>1));
+    } else
+    {
+        if( inHeight < outHeight)
+        {
+            // pad height
+            WebRtc_Word32 padH = outHeight - inHeight;
+            WebRtc_UWord32 i =0;
+            WebRtc_Word32 padW = 0;
+            WebRtc_Word32 cutW = 0;
+            WebRtc_Word32 width = inWidth;
+            if (inWidth < outWidth)
+            {
+                // pad width
+                padW = outWidth - inWidth;
+            } else
+            {
+              // cut width
+              cutW = inWidth - outWidth;
+              width = outWidth;
+            }
+            if (padH)
+            {
+                memset(outFrame, 0, outWidth * (padH >> 1));
+                outFrame +=  outWidth * (padH >> 1);
+            }
+            for (i = 0; i < inHeight;i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 0, padW / 2);
+                    outFrame +=  padW / 2;
+                }
+                inFrame += cutW >> 1; // in case we have a cut
+                memcpy(outFrame,inFrame ,width);
+                inFrame += cutW >> 1;
+                outFrame += width;
+                inFrame += width;
+                if (padW)
+                {
+                    memset(outFrame, 0, padW / 2);
+                    outFrame +=  padW / 2;
+                }
+            }
+            if (padH)
+            {
+                memset(outFrame, 0, outWidth * (padH >> 1));
+                outFrame +=  outWidth * (padH >> 1);
+            }
+            if (padH)
+            {
+                memset(outFrame, 127, (outWidth >> 2) * (padH >> 1));
+                outFrame +=  (outWidth >> 2) * (padH >> 1);
+            }
+            for (i = 0; i < (inHeight >> 1); i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+                inFrame += cutW >> 2; // in case we have a cut
+                memcpy(outFrame, inFrame,width >> 1);
+                inFrame += cutW >> 2;
+                outFrame += width >> 1;
+                inFrame += width >> 1;
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+            }
+            if (padH)
+            {
+                memset(outFrame, 127, (outWidth >> 1) * (padH >> 1));
+                outFrame +=  (outWidth >> 1) * (padH >> 1);
+            }
+            for (i = 0; i < (inHeight >> 1); i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+                inFrame += cutW >> 2; // in case we have a cut
+                memcpy(outFrame, inFrame,width >> 1);
+                inFrame += cutW >> 2;
+                outFrame += width >> 1;
+                inFrame += width >> 1;
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame += padW >> 2;
+                }
+            }
+            if (padH)
+            {
+                memset(outFrame, 127, (outWidth >> 2) * (padH >> 1));
+                outFrame +=  (outWidth >> 2) * (padH >> 1);
+            }
+        } else
+        {
+            // cut height
+            WebRtc_UWord32 i =0;
+            WebRtc_Word32 padW = 0;
+            WebRtc_Word32 cutW = 0;
+            WebRtc_Word32 width = inWidth;
+
+            if (inWidth < outWidth)
+            {
+                // pad width
+                padW = outWidth - inWidth;
+            } else
+            {
+                // cut width
+                cutW = inWidth - outWidth;
+                width = outWidth;
+            }
+            WebRtc_Word32 diffH = inHeight - outHeight;
+            inFrame += inWidth * (diffH >> 1);  // skip top I
+
+            for (i = 0; i < outHeight; i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 0, padW / 2);
+                    outFrame +=  padW / 2;
+                }
+                inFrame += cutW >> 1; // in case we have a cut
+                memcpy(outFrame,inFrame ,width);
+                inFrame += cutW >> 1;
+                outFrame += width;
+                inFrame += width;
+                if (padW)
+                {
+                    memset(outFrame, 0, padW / 2);
+                    outFrame +=  padW / 2;
+                }
+            }
+            inFrame += inWidth * (diffH >> 1);  // skip end I
+            inFrame += (inWidth >> 2) * (diffH >> 1); // skip top of Cr
+            for (i = 0; i < (outHeight >> 1); i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+                inFrame += cutW >> 2; // in case we have a cut
+                memcpy(outFrame, inFrame,width >> 1);
+                inFrame += cutW >> 2;
+                outFrame += width >> 1;
+                inFrame += width >> 1;
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+            }
+            inFrame += (inWidth >> 2) * (diffH >> 1); // skip end of Cr
+            inFrame += (inWidth >> 2) * (diffH >> 1); // skip top of Cb
+            for (i = 0; i < (outHeight >> 1); i++)
+            {
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+                inFrame += cutW >> 2; // in case we have a cut
+                memcpy(outFrame, inFrame, width >> 1);
+                inFrame += cutW >> 2;
+                outFrame += width >> 1;
+                inFrame += width >> 1;
+                if (padW)
+                {
+                    memset(outFrame, 127, padW >> 2);
+                    outFrame +=  padW >> 2;
+                }
+            }
+        }
+    }
+    return 3 * outWidth * (outHeight >> 1);
+}
+
+WebRtc_Word32
+ConvertRGB24ToARGB(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                   WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    }
+    else if (strideOut < width)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord32 i, j, offset;
+
+    outFrame += strideOut * (height - 1) * 4;
+    for(i = 0; i < height; i++)
+    {
+        for(j = 0; j < width; j++)
+        {
+            offset = j*4;
+            outFrame[0 + offset] = inFrame[0];
+            outFrame[1 + offset] = inFrame[1];
+            outFrame[2 + offset] = inFrame[2];
+            outFrame[3 + offset] = 0xff;
+            inFrame += 3;
+        }
+        outFrame -= 4 * (strideOut - width);
+    }
+    return strideOut * height * 4;
+}
+
+WebRtc_Word32
+ConvertRGB24ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 inWidth, WebRtc_UWord32 inHeight,
+                   WebRtc_UWord8* outFrame, WebRtc_UWord32 outWidth, WebRtc_UWord32 outHeight)
+{
+    if (inWidth < 1 || outWidth < 1 || inHeight < 1 || outHeight < 1 )
+    {
+        return -1;
+    }
+    WebRtc_UWord32* yStartPtr = (WebRtc_UWord32*)(outFrame + (outWidth * outHeight));
+    WebRtc_UWord8* uStartPtr = outFrame + (outWidth * outHeight) + ((outWidth * outHeight) >> 2);
+    WebRtc_UWord8* vStartPtr = outFrame + (outWidth * outHeight) +((outWidth * outHeight) >> 1);
+
+    yStartPtr--;
+    uStartPtr--;
+    vStartPtr--;
+    const WebRtc_UWord8* inpPtr;
+    const WebRtc_UWord8* inFramePtr = inFrame;
+    WebRtc_Word32 offset = 0;
+    WebRtc_Word32 height = inHeight;
+    WebRtc_Word32 cutDiff = 0;
+    WebRtc_Word32 padDiffLow= 0;
+    WebRtc_Word32 padDiffHigh = 0;
+
+    if (inHeight > outHeight)
+    {
+        // cut height
+        inFramePtr += inWidth*3 * ((inHeight - outHeight) >> 1); // skip the first diff/2 rows
+        height = outHeight;
+    }
+    if (outHeight > inHeight)
+    {
+        // Pad height.
+        WebRtc_UWord8* outI = outFrame;
+        WebRtc_UWord8* outCr = outFrame + outWidth * outHeight;
+        WebRtc_UWord8* outCb = outCr + ((outWidth * outHeight) >> 2);
+
+        // -- I --
+        WebRtc_UWord32 padHeight = outHeight - inHeight;
+        WebRtc_UWord32 padHeightT = padHeight >> 1;
+        WebRtc_UWord32 padHeightB = padHeight - padHeightT;
+        WebRtc_UWord32 padLength = padHeightT * outWidth;
+        memset(outI, 0, padLength); // Pad the top.
+        outI += padLength;
+
+        outI += outWidth * inHeight; // Skip the image.
+        padLength = padHeightB * outWidth;
+        memset(outI, 0, padLength); // Pad the bottom.
+
+        // Shift the out poWebRtc_Word32er.
+        yStartPtr -= (padLength >> 2); // (>> 2) due to WebRtc_Word32 pointer.
+
+        // -- Cr and Cb --
+        padHeight >>= 1;
+        padHeightT >>= 1;
+        padHeightB = padHeight - padHeightT;
+
+        padLength = padHeightT * (outWidth >> 1);
+        memset(outCr, 127, padLength); // Pad the top.
+        memset(outCb, 127, padLength);
+        outCr += padLength;
+        outCb += padLength;
+
+        padLength = (outWidth * inHeight) >> 2;
+        outCr += padLength; // Skip the image.
+        outCb += padLength;
+        padLength = padHeightB * (outWidth >> 1);
+        memset(outCr, 127, padLength); // Pad the bottom.
+        memset(outCb, 127, padLength);
+
+        // Shift the out pointers.
+        uStartPtr -= padLength;
+        vStartPtr -= padLength;
+    }
+    // cut width?
+    if (inWidth > outWidth)
+    {
+        cutDiff = (inWidth - outWidth) >> 1; // in pixels
+    }
+    // pad width?
+    if (inWidth < outWidth)
+    {
+        padDiffLow = (outWidth - inWidth) >> 1; // in pixels
+        padDiffHigh = (outWidth - inWidth) - padDiffLow; // in pixels
+    }
+
+    for (WebRtc_Word32 y = 0; y < height; y++)
+    {
+        offset = y * inWidth * 3;
+        inpPtr = &inFramePtr[offset + (inWidth - 4) * 3]; // right to left
+        inpPtr -= 3*cutDiff;
+        WebRtc_Word32 i = (inWidth - (cutDiff * 2)) >> 2;
+        WebRtc_UWord32 tmp;
+        if (padDiffLow)
+        {
+            yStartPtr -= padDiffLow >> 2; //div by 4 since its a WebRtc_Word32 ptr
+            memset(yStartPtr + 1, 0, padDiffLow);
+        }
+        for (; i > 0; i--) // do 4 pixels wide in one loop
+        {
+#ifdef  WEBRTC_BIG_ENDIAN
+            tmp = (WebRtc_UWord8)((66 * inpPtr[2] + 129 * inpPtr[1] + 25 * inpPtr[0] + 128)
+                   >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[4] + 25 * inpPtr[3] + 128)
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 *  inpPtr[8] + 129 * inpPtr[7] + 25 * inpPtr[6] + 128)
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[11] + 129 * inpPtr[10] + 25 * inpPtr[9] + 128)
+                    >> 8) + 16;
+
+#else
+            tmp = (WebRtc_UWord8)((66 * inpPtr[11] + 129 * inpPtr[10] + 25 * inpPtr[9] + 128) >> 8)
+                   + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[8] + 129 * inpPtr[7] + 25 * inpPtr[6] + 128) >> 8)
+                    + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[4] + 25 * inpPtr[3] + 128) >> 8)
+                    + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[2] + 129 * inpPtr[1] + 25 * inpPtr[0] + 128) >> 8)
+                    + 16;
+#endif
+            *yStartPtr = tmp;
+            yStartPtr--;
+            inpPtr -= 12;
+        }
+        if (padDiffHigh)
+        {
+            yStartPtr -= padDiffHigh >> 2; //div by 4 since its a WebRtc_Word32 ptr
+            memset(yStartPtr + 1, 0, padDiffHigh);
+        }
+        y++; // doing an ugly add to my loop variable
+        offset = y * inWidth * 3;
+        inpPtr = &inFramePtr[offset + (inWidth - 4) * 3];
+        inpPtr -= 3 * cutDiff;
+        i = (inWidth - (cutDiff * 2)) >> 2;
+
+        if (padDiffLow)
+        {
+            yStartPtr -= padDiffLow >> 2; //div by 4 since its a WebRtc_Word32 ptr
+            uStartPtr -= padDiffLow >> 1;
+            vStartPtr -= padDiffLow >> 1;
+            memset(yStartPtr + 1, 0, padDiffLow);
+            memset(uStartPtr + 1, 127, padDiffLow >> 1);
+            memset(vStartPtr + 1, 127, padDiffLow >> 1);
+        }
+        for (; i > 0; i--)
+        {
+            *uStartPtr = (WebRtc_UWord8)((-38 * inpPtr[8] - 74 * inpPtr[7] + 112 * inpPtr[6] + 128)
+                          >> 8) + 128;
+            uStartPtr--;
+            *vStartPtr = (WebRtc_UWord8)((112 * inpPtr[8] - 94 * inpPtr[7] - 18 * inpPtr[6] + 128)
+                          >> 8) + 128;
+            vStartPtr--;
+            *uStartPtr = (WebRtc_UWord8)((-38 * inpPtr[2] - 74 * inpPtr[1] + 112 * inpPtr[0] + 128)
+                          >> 8) + 128;
+            uStartPtr--;
+            *vStartPtr = (WebRtc_UWord8)((112 * inpPtr[2] - 94 * inpPtr[1] - 18 * inpPtr[0] + 128)
+                          >> 8) + 128;
+            vStartPtr--;
+#ifdef WEBRTC_BIG_ENDIAN
+            tmp = (WebRtc_UWord8)((66 * inpPtr[2] + 129 * inpPtr[1] + 25 * inpPtr[0] + 128 )
+                   >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[4] + 25 * inpPtr[3] + 128)
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[8] + 129 * inpPtr[7] + 25 * inpPtr[6] + 128)
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[11] + 129 * inpPtr[10] + 25 * inpPtr[9] + 128)
+                    >> 8) + 16;
+#else
+            tmp = (WebRtc_UWord8)((66 * inpPtr[11] + 129 * inpPtr[10] + 25 * inpPtr[9]+ 128)
+                   >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[8] + 129 * inpPtr[7] + 25 * inpPtr[6] + 128)
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[4] + 25 * inpPtr[3] + 128 )
+                    >> 8) + 16;
+            tmp = tmp << 8;
+            tmp += (WebRtc_UWord8)((66 * inpPtr[2] + 129 * inpPtr[1] + 25 * inpPtr[0] + 128)
+                    >> 8) + 16;
+#endif
+            *yStartPtr = tmp;
+            yStartPtr--;
+            inpPtr -= 12;
+        }
+        if (padDiffHigh)
+        {
+            yStartPtr -= padDiffHigh >> 2; //div by 4 since its a WebRtc_Word32 ptr
+            uStartPtr -= padDiffHigh >> 1;
+            vStartPtr -= padDiffHigh >> 1;
+            memset(yStartPtr + 1, 0, padDiffHigh);
+            memset(uStartPtr + 1, 127, padDiffHigh >> 1);
+            memset(vStartPtr + 1, 127, padDiffHigh >> 1);
+        }
+    }
+    return (outWidth >> 1) * outHeight * 3;
+}
+
+
+WebRtc_Word32
+ConvertRGB24ToI420(WebRtc_UWord32 width, WebRtc_UWord32 height, const WebRtc_UWord8* inFrame,
+                   WebRtc_UWord8* outFrame)
+{
+    if (height < 1 || width < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord8* yStartPtr;
+    WebRtc_UWord8* yStartPtr2;
+    WebRtc_UWord8* uStartPtr;
+    WebRtc_UWord8* vStartPtr;
+    const WebRtc_UWord8* inpPtr;
+    const WebRtc_UWord8* inpPtr2;
+
+    // assuming RGB in a bottom up orientation.
+    yStartPtr = outFrame;
+    yStartPtr2 = yStartPtr + width;
+    uStartPtr = outFrame + (width * height);
+    vStartPtr = uStartPtr + (width * height >> 2);
+    inpPtr = inFrame + width * height * 3 - 3 * width;
+    inpPtr2 = inpPtr - 3 * width;
+
+    for (WebRtc_UWord32 h = 0; h < (height >> 1); h++ )
+    {
+        for (WebRtc_UWord32 w = 0; w < (width >> 1); w++)
+        {
+            //Y
+            yStartPtr[0] =  (WebRtc_UWord8)((66 * inpPtr[2] + 129 * inpPtr[1] + 25 * inpPtr[0]
+                                             + 128) >> 8) + 16;
+            yStartPtr2[0] = (WebRtc_UWord8)((66 * inpPtr2[2] + 129 * inpPtr2[1] + 25 * inpPtr2[0]
+                                             + 128) >> 8) + 16;
+            // moving to next column
+            yStartPtr[1] = (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[4] + 25 * inpPtr[3]
+                                            + 128) >> 8) + 16;
+            yStartPtr2[1] = (WebRtc_UWord8)((66 * inpPtr2[5] + 129 * inpPtr2[4] + 25 * inpPtr2[3]
+                                             + 128) >> 8 ) + 16;
+            //U
+            uStartPtr[0] = (WebRtc_UWord8)((-38 * inpPtr[2] - 74 * inpPtr[1] + 112 * inpPtr[0]
+                                            + 128) >> 8) + 128;
+            //V
+            vStartPtr[0] = (WebRtc_UWord8)((112 * inpPtr[2] -94 * inpPtr[1] -18 * inpPtr[0]
+                                            + 128) >> 8) + 128;
+
+            yStartPtr += 2;
+            yStartPtr2 += 2;
+            uStartPtr++;
+            vStartPtr++;
+            inpPtr += 6;
+            inpPtr2 += 6;
+        } // end for w
+        yStartPtr += width;
+        yStartPtr2 += width;
+        inpPtr -= 9 * width;
+        inpPtr2 -= 9 * width;
+    } // end for h
+    return (width >> 1) * height * 3;
+}
+
+WebRtc_Word32
+ConvertI420ToARGBMac(const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                     WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 strideOut)
+{
+    if (height < 1 || width < 1)
+    {
+        return -1;
+    }
+    if (strideOut == 0)
+    {
+        strideOut = width;
+    } else if (strideOut  < width)
+    {
+        return -1;
+    }
+    WebRtc_Word32 diff = strideOut - width;
+    WebRtc_UWord8* out = outFrame;
+    WebRtc_UWord8* out2 = out + strideOut * 4;
+    const WebRtc_UWord8 *y1,*y2, *u, *v;
+    WebRtc_UWord32 h, w;
+    y1 = inFrame;
+    y2 = y1 + width;
+    v = y1 + width * height;
+    u = v + ((width * height) >> 2);
+
+    for (h = (height >> 1); h > 0; h--)
+    {
+      WebRtc_Word32 tmpG, tmpB, tmpR;
+        //do 2 rows at the time
+        for (w = 0; w < (width >> 1); w++)
+        {
+            tmpR = (WebRtc_Word32)((mapYc[y1[0]] + mapVcr[v[0]] + 128  )>> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[0]] + mapUcb[u[0]] + 128 )>> 8);
+            out[2] = Clip(tmpR);
+            out[1] = Clip(tmpG);
+            out[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8);
+            out2[2] = Clip(tmpR);
+            out2[1] = Clip(tmpG);
+            out2[0] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y1[1]] + mapVcr[v[0]] + 128)>> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8);
+            out[6] = Clip(tmpR);
+            out[5] = Clip(tmpG);
+            out[4] = Clip(tmpB);
+
+            tmpR = (WebRtc_Word32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8);
+            tmpG = (WebRtc_Word32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8);
+            tmpB = (WebRtc_Word32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8);
+            out2[6] = Clip(tmpR);
+            out2[5] = Clip(tmpG);
+            out2[4] = Clip(tmpB);
+
+
+            out[3] = 0xff;
+            out[7] = 0xff;
+            out += 8;
+            out2[3] = 0xff;
+            out2[7] = 0xff;
+            out2 += 8;
+            y1 += 2;
+            y2 += 2;
+            u++;
+            v++;
+        }
+
+        y1 += width;
+        y2 += width;
+        out += (width + diff * 2) * 4;
+        out2 += (width + diff * 2) * 4;
+    }
+    return strideOut * height * 4;
+}
+
+WebRtc_Word32
+ConvertRGB565ToI420(const WebRtc_UWord8* inFrame, WebRtc_UWord32 width, WebRtc_UWord32 height,
+                    WebRtc_UWord8* outFrame)
+{
+    if (width < 1 || height < 1 )
+    {
+        return -1;
+    }
+    WebRtc_UWord8 tmpR, tmpG, tmpB;
+    WebRtc_UWord8 tmpR2, tmpG2, tmpB2;
+
+    WebRtc_UWord8* yStartPtr = outFrame;
+    WebRtc_UWord8* yStartPtr2 = yStartPtr + width;
+    WebRtc_UWord8* uStartPtr = outFrame + (width * height);
+    WebRtc_UWord8* vStartPtr = uStartPtr + (width * height >> 2);
+    const WebRtc_UWord16* inpPtr = (const WebRtc_UWord16*)inFrame;
+    inpPtr += width * (height - 1);
+    const WebRtc_UWord16* inpPtr2 = inpPtr - width;
+
+    for (WebRtc_UWord32 h = 0; h < (height >> 1); h++ )
+    {
+        for (WebRtc_UWord32 w = 0; w < (width >> 1); w++)
+        {
+          // calculating 8 bit values
+            tmpB = (WebRtc_UWord8)((inpPtr[0] & 0x001F) << 3);
+            tmpG = (WebRtc_UWord8)((inpPtr[0] & 0x07E0) >> 3);
+            tmpR = (WebRtc_UWord8)((inpPtr[0] & 0xF800) >> 8);
+            tmpB2 = (WebRtc_UWord8)((inpPtr2[0] & 0x001F) << 3);
+            tmpG2 = (WebRtc_UWord8)((inpPtr2[0] & 0x07E0) >> 3);
+            tmpR2 = (WebRtc_UWord8)((inpPtr2[0] & 0xF800) >> 8);
+
+            //Y
+            yStartPtr[0] = (WebRtc_UWord8)((66 * tmpR + 129 * tmpG + 25 * tmpB + 128) >> 8)
+                                            + 16;
+            //U
+            uStartPtr[0] = (WebRtc_UWord8)((-38 * tmpR - 74 * tmpG + 112 * tmpB + 128) >> 8)
+                                            + 128;
+            //V
+            vStartPtr[0] = (WebRtc_UWord8)((112 * tmpR - 94 * tmpG - 18 * tmpB + 128) >> 8)
+                                            + 128;
+
+            yStartPtr2[0] = (WebRtc_UWord8)((66 * tmpR2 + 129 * tmpG2 + 25 * tmpB2 + 128) >> 8)
+                                             + 16;
+
+            // moving to next column
+            tmpB = (WebRtc_UWord8)((inpPtr[1] & 0x001F) << 3);
+            tmpG = (WebRtc_UWord8)((inpPtr[1] & 0x07E0) >> 3);
+            tmpR = (WebRtc_UWord8)((inpPtr[1] & 0xF800) >> 8);
+
+            tmpB2 = (WebRtc_UWord8)((inpPtr2[1] & 0x001F) << 3);
+            tmpG2 = (WebRtc_UWord8)((inpPtr2[1] & 0x07E0) >> 3);
+            tmpR2 = (WebRtc_UWord8)((inpPtr2[1] & 0xF800) >> 8);
+
+            yStartPtr[1] =  (WebRtc_UWord8)((66 * tmpR + 129 * tmpG + 25 * tmpB + 128) >> 8) + 16;
+            yStartPtr2[1] =  (WebRtc_UWord8)((66 * tmpR2 +129 * tmpG2 + 25 * tmpB2 + 128) >> 8) + 16;
+
+            yStartPtr += 2;
+            yStartPtr2 += 2;
+            uStartPtr++;
+            vStartPtr++;
+            inpPtr += 2;
+            inpPtr2 += 2;
+        }
+        yStartPtr += width;
+        yStartPtr2 += width;
+        inpPtr -= 3 * width;
+        inpPtr2 -= 3 * width;
+    }
+    return (width >> 1) * height * 3;
+}
+
+WebRtc_Word32
+ConvertARGBMacToI420(WebRtc_UWord32 width, WebRtc_UWord32 height, const WebRtc_UWord8* inFrame,
+                  WebRtc_UWord8* outFrame)
+{
+    if (height < 1 || width < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord8* yStartPtr;
+    WebRtc_UWord8* yStartPtr2;
+    WebRtc_UWord8* uStartPtr;
+    WebRtc_UWord8* vStartPtr;
+    const WebRtc_UWord8* inpPtr;
+    const WebRtc_UWord8* inpPtr2;
+
+    yStartPtr = outFrame;
+    yStartPtr2 = yStartPtr + width;
+    uStartPtr = outFrame + (width * height);
+    vStartPtr = uStartPtr + (width * height >> 2);
+    inpPtr = inFrame;
+    inpPtr2 = inpPtr + 4 * width;
+    WebRtc_UWord32 h, w;
+    for (h = 0; h < (height >> 1); h++)
+    {
+        for (w = 0; w < (width >> 1); w++)
+        {   //Y
+            yStartPtr[0]  = (WebRtc_UWord8)((66 * inpPtr[1] + 129 * inpPtr[2]
+                                             + 25 * inpPtr[3] + 128) >> 8) + 16;
+            yStartPtr2[0] = (WebRtc_UWord8)((66 * inpPtr2[1] + 129 * inpPtr2[2]
+                                             + 25 * inpPtr2[3] + 128) >> 8) + 16;
+            // moving to next column
+            yStartPtr[1] =  (WebRtc_UWord8)((66 * inpPtr[5] + 129 * inpPtr[6]
+                                             + 25 * inpPtr[7] + 128) >> 8) + 16;
+            yStartPtr2[1] = (WebRtc_UWord8)((66 * inpPtr2[5] + 129 * inpPtr2[6]
+                                             + 25 * inpPtr2[7] + 128) >> 8) + 16;
+            //U
+            uStartPtr[0] = (WebRtc_UWord8)((-38 * inpPtr[1] - 74 * inpPtr[2]
+                                            + 112 * inpPtr[3] + 128) >> 8) + 128;
+            //V
+            vStartPtr[0] = (WebRtc_UWord8)((112 * inpPtr[1] - 94 * inpPtr[2]
+                                            - 18 * inpPtr[3] + 128) >> 8) + 128;
+
+            yStartPtr += 2;
+            yStartPtr2 += 2;
+            uStartPtr++;
+            vStartPtr++;
+            inpPtr += 8;
+            inpPtr2 += 8;
+        }
+        yStartPtr += width;
+        yStartPtr2 += width;
+        inpPtr += 4 * width;
+        inpPtr2 += 4 * width;
+    }
+    return (width * height * 3 >> 1);
+}
+
+
+WebRtc_Word32
+PadI420BottomRows(WebRtc_UWord8* inputVideoBuffer, WebRtc_UWord32 size, WebRtc_UWord32 width,
+                  WebRtc_UWord32 height, WebRtc_Word32 nrRows, WebRtc_UWord32& newLength)
+{
+    // sanity
+    WebRtc_UWord32 length = 3 * (width >> 1) * (height + nrRows);
+    if (size < length)
+        return -1;
+
+    if (nrRows < 0)
+        return -1;
+
+    WebRtc_Word32 colorSize = (width * height) >> 2;
+    WebRtc_Word32 padSize = width * nrRows;
+    WebRtc_Word32 padSizeColor = (width * nrRows) >> 2;
+    WebRtc_Word32 outColorSize = (width *(height + nrRows)) >> 2;
+    WebRtc_Word32 j = width * (height + nrRows) + outColorSize;
+
+    WebRtc_Word32 i = width*height + colorSize; // start of Cr
+    memmove(&inputVideoBuffer[j], &inputVideoBuffer[i], colorSize);
+    memset((&inputVideoBuffer[j])+colorSize,127,padSizeColor);
+
+    i = width*height; // start of Cb
+    j = width*(height+nrRows);
+    memmove(&inputVideoBuffer[j], &inputVideoBuffer[i], colorSize);
+    memset((&inputVideoBuffer[j])+colorSize,127,padSizeColor);
+
+    memset(&inputVideoBuffer[i],0,padSize);
+
+    newLength = length;
+    return 0;
+}
+
+
+static WebRtc_UWord32
+PadI420Component(const WebRtc_UWord8* inBuf, WebRtc_UWord8* outBuf,
+                 const WebRtc_UWord32 fromWidth, const WebRtc_UWord32 fromHeight,
+                 const WebRtc_UWord32 padWidth,  const WebRtc_UWord32 padWidthL,
+                 const WebRtc_UWord32 padHeight, const WebRtc_UWord32 padHeightT,
+                 const WebRtc_UWord8 padValue)
+{
+    const WebRtc_Word32 toWidth = fromWidth + padWidth;
+    const WebRtc_Word32 padWidthR = padWidth - padWidthL;
+    const WebRtc_Word32 padHeightB = padHeight - padHeightT;
+
+    // Top border
+    memset(outBuf, padValue, toWidth * padHeightT);
+    WebRtc_UWord32 outIdx = toWidth * padHeightT;
+    WebRtc_UWord32 inIdx = 0;
+    for (WebRtc_UWord32 i = 0; i < fromHeight; i++)
+    {
+        // Left border
+        memset(&outBuf[outIdx], padValue, padWidthL);
+        outIdx += padWidthL;
+
+        // Copy image
+        memcpy(&outBuf[outIdx], &inBuf[inIdx], fromWidth);
+        outIdx += fromWidth;
+        inIdx += fromWidth;
+
+        // Right border
+        memset(&outBuf[outIdx], padValue, padWidthR);
+        outIdx += padWidthR;
+    }
+    // Bottom border
+    memset(&outBuf[outIdx], padValue, toWidth * padHeightB);
+    outIdx += toWidth * padHeightB;
+
+    return outIdx;
+}
+
+WebRtc_Word32
+PadI420Frame(const WebRtc_UWord8* inBuffer, WebRtc_UWord8* outBuffer, WebRtc_UWord32 fromWidth,
+             WebRtc_UWord32 fromHeight, WebRtc_UWord32 toWidth, WebRtc_UWord32 toHeight)
+{
+    if (toWidth < 1 || fromWidth < 1 || toHeight < 1 || fromHeight < 1)
+    {
+        return -1;
+    }
+    if (toWidth == fromWidth && toHeight == fromHeight)
+    {
+        // nothing to do
+        return (3 * toHeight * toWidth) >> 1;
+    }
+
+    if (inBuffer == NULL)
+    {
+        return -1;
+    }
+
+    if (outBuffer == NULL)
+    {
+        return -1;
+    }
+
+    if (fromWidth < 0 || fromHeight < 0)
+    {
+        return -1;
+    }
+
+    if (toWidth < 0 || toHeight < 0)
+    {
+        return -1;
+    }
+
+    if (toWidth < fromWidth || toHeight < fromHeight)
+    {
+        return -1;
+    }
+
+    WebRtc_UWord32 padWidth = toWidth - fromWidth;
+    WebRtc_UWord32 padHeight = toHeight - fromHeight;
+    WebRtc_UWord32 padWidthL = 0;
+    WebRtc_UWord32 padHeightT = 0;
+
+    // If one of the padded dimensions is a multiple of 16, we apply the padding in
+    // blocks of 16.
+    if (padHeight % 16 == 0)
+    {
+        WebRtc_UWord32 num16blocks = padHeight >> 4;
+        padHeightT = ((num16blocks >> 1) << 4); // NOTE: not the same as
+                                                //       num16blocks << 3
+    }
+    else
+    {
+        padHeightT = padHeight >> 1;
+    }
+
+    if (padWidth % 16 == 0)
+    {
+        WebRtc_UWord32 num16blocks = padWidth >> 4;
+        padWidthL = ((num16blocks >> 1) << 4);
+    }
+    else
+    {
+        padWidthL = padWidth >> 1;
+    }
+
+    // -- I --
+    WebRtc_UWord32 inIdx = 0;
+    WebRtc_UWord32 outIdx = 0;
+    outIdx = PadI420Component(&inBuffer[inIdx], &outBuffer[outIdx], fromWidth,
+                              fromHeight, padWidth, padWidthL, padHeight, padHeightT, 0);
+    // -- Cr --
+    inIdx = fromWidth * fromHeight;
+    fromWidth >>= 1;
+    fromHeight >>= 1;
+    padWidth >>= 1;
+    padWidthL >>= 1;
+    padHeight >>= 1;
+    padHeightT >>= 1;
+    outIdx += PadI420Component(&inBuffer[inIdx], &outBuffer[outIdx], fromWidth,
+                               fromHeight, padWidth, padWidthL, padHeight, padHeightT, 127);
+    // -- Cb --
+    inIdx += fromWidth * fromHeight;
+    outIdx += PadI420Component(&inBuffer[inIdx], &outBuffer[outIdx], fromWidth,
+                               fromHeight, padWidth, padWidthL, padHeight, padHeightT, 127);
+
+    return outIdx;
+}
+
+WebRtc_Word32
+PadI420Frame(WebRtc_UWord32 size, const WebRtc_UWord8* inBuffer, WebRtc_UWord8* outBuffer,
+             bool block16Bit)
+{
+    if (size < 1)
+    {
+        return -1;
+    }
+    WebRtc_Word32 i = 0;
+    WebRtc_Word32 m = 0;
+    WebRtc_Word32 loop = 0;
+    WebRtc_Word32 dropHeightBits = 0; // must be a factor of 4
+    WebRtc_Word32 halfToWidth;
+    WebRtc_Word32 halfToHeight;
+    WebRtc_Word32 halfFromWidth;
+    WebRtc_Word32 halfFromHeight;
+    WebRtc_Word32 padHeightT;
+    WebRtc_Word32 padHeightB;
+    WebRtc_Word32 padWidthL;
+    WebRtc_Word32 padWidthR;
+    WebRtc_Word32 toWidth;
+    WebRtc_Word32 toHeight;
+    WebRtc_Word32 fromWidth;
+    WebRtc_Word32 fromHeight;
+    if (block16Bit)
+    {
+        if (size == 115200) // to 152064
+        {
+            toWidth = 352;
+            toHeight = 288;
+            fromWidth = 320;
+            fromHeight =240;
+            padHeightT = 16;
+            padHeightB = 32;
+            padWidthL = 16;
+            padWidthR = 16;
+        } else if (size == 28800)
+        {
+            fromWidth = 160;
+            fromHeight =120;
+            dropHeightBits = 8; // drop 8 bits
+            toWidth = 176;
+            toHeight = 144;
+            padHeightT = 16;
+            padHeightB = 16;
+            padWidthL = 0;
+            padWidthR = 16;
+        } else
+        {
+            return -1;
+        }
+    } else
+    {
+        return -1;
+    }
+    halfFromWidth = fromWidth >> 1;
+    halfFromHeight = fromHeight >> 1;
+    halfToWidth = toWidth >> 1;
+    halfToHeight = toHeight >> 1;
+
+    //Ilum
+    memset(outBuffer,0,toWidth * padHeightT + padWidthL); // black
+    i =  toWidth * padHeightT + padWidthL;
+    m = (dropHeightBits >> 1) * fromWidth;
+    for (loop = 0; loop < (fromHeight - dropHeightBits); loop++)
+    {
+        memcpy(&outBuffer[i], &inBuffer[m],fromWidth);
+        i += fromWidth;
+        m += fromWidth;
+        memset(&outBuffer[i],0,padWidthL + padWidthR); // black
+        i += padWidthL + padWidthR;
+    }
+    memset(&outBuffer[i],0,toWidth * padHeightB - padWidthL); // black
+    m += (dropHeightBits >> 1) * fromWidth;
+    i = toWidth * toHeight; // ilum end
+
+    // Cr
+    memset(&outBuffer[i],127,halfToWidth * (padHeightT >> 1) + (padWidthL >> 1) ); // black
+    i += halfToWidth * (padHeightT >> 1) + (padWidthL >> 1);
+
+    m += (dropHeightBits >> 2) * halfFromWidth;
+    for(loop =0 ; loop < (halfFromHeight - (dropHeightBits >> 1)); loop++)
+    {
+        memcpy(&outBuffer[i],&inBuffer[m],halfFromWidth);
+        m += halfFromWidth;
+        i += halfFromWidth;
+        memset(&outBuffer[i],127,(padWidthL + padWidthR) >> 1); // black
+        i += (padWidthL + padWidthR) >> 1;
+    }
+    memset(&outBuffer[i],127,halfToWidth * (padHeightB >> 1) - (padWidthL >> 1) ); // black
+    m += (dropHeightBits>>2) * halfFromWidth;
+    i = toWidth * toHeight + halfToHeight * halfToWidth; // ilum +Cr
+
+    // Cb
+    memset(&outBuffer[i],127,halfToWidth * (padHeightT >> 1) + (padWidthL >> 2)); // black
+    i += halfToWidth * (padHeightT >> 1) + (padWidthL >> 1);
+
+    m += (dropHeightBits >> 2) * halfFromWidth;
+    for(loop = 0; loop < (halfFromHeight - (dropHeightBits >> 1)); loop++)
+    {
+        memcpy(&outBuffer[i],&inBuffer[m],halfFromWidth);
+        m += halfFromWidth;
+        i += halfFromWidth;
+        memset(&outBuffer[i],127,((padWidthL + padWidthR) >> 1)); // black
+        i+=((padWidthL + padWidthR) >> 1);
+    }
+    memset(&outBuffer[i],127,halfToWidth * (padHeightB >> 1) - (padWidthL >> 1) ); // black
+    return halfToWidth * toHeight * 3;
+}
+
+WebRtc_Word32
+ScaleI420UpHalfFrame(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8* inFrame)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord8* inPtr = inFrame + (width * height / 4 * 3) -1;
+    WebRtc_UWord8* outPtr = inFrame + (width * height / 2 * 3) -1;
+
+    for(WebRtc_Word32 i = (width * height / 4 * 3)-1; i > 0; i--)
+    {
+        *outPtr = *inPtr;
+        outPtr--;
+        inPtr--;
+        *outPtr = ((inPtr[0] + inPtr[1]) / 2);
+        outPtr--;
+    }
+    *outPtr = *inPtr;
+    outPtr--;
+    *outPtr = *inPtr;
+
+    return 3 * width * height / 2;
+}
+
+WebRtc_Word32
+ScaleI420DownHalfFrame(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8* inFrame)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord8* inPtr1 = inFrame;
+    WebRtc_UWord8* outPtr = inFrame;
+    WebRtc_UWord32 y = 0;
+    WebRtc_UWord32 x = 0;
+    // ilum
+    for(; y < (height); y++)
+    {
+        for(x = 0; x < (width >> 1); x++)
+        {
+            WebRtc_Word32 avg = inPtr1[0] + inPtr1[1];
+            avg = avg >>1;
+            *outPtr= (WebRtc_UWord8)(avg);
+            inPtr1 += 2;
+            outPtr++;
+        }
+    }
+    inPtr1 = inFrame + (width * height);
+
+    // color
+    for(y = 0; y < height; y++)
+    {
+        // 2 rows
+        for(x = 0; x < (width >> 2); x++)
+        {
+            WebRtc_Word32 avg = inPtr1[0] + inPtr1[1] ;
+            *outPtr = (WebRtc_UWord8)(avg >> 1);
+            inPtr1 += 2;
+            outPtr++;
+        }
+    }
+    return height * (width >> 1) * 3;
+}
+
+WebRtc_Word32
+ScaleI420FrameQuarter(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8* inFrame)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord8* inPtr1 = inFrame;
+    WebRtc_UWord8* inPtr2 = inFrame + width;
+    WebRtc_UWord8* outPtr = inFrame;
+
+    WebRtc_UWord32 y = 0;
+    WebRtc_UWord32 x = 0;
+    // ilum
+    for(; y < (height >> 1); y++)
+    {
+        // 2 rows
+        for(x = 0; x < (width >> 1); x++)
+        {
+            WebRtc_Word32 avg = inPtr1[0] + inPtr2[0] + inPtr1[1] + inPtr2[1];
+            *outPtr= (WebRtc_UWord8)(avg >> 2);
+            inPtr1 += 2;
+            inPtr2 += 2;
+            outPtr++;
+        }
+        inPtr1 +=width;
+        inPtr2 +=width;
+    }
+
+    inPtr1 = inFrame + (width * height);
+    inPtr2 = inPtr1 + (width>>1);
+
+    // color
+    for(y = 0; y < (height>>1); y++)
+    {
+        // 2 rows
+        for(x = 0; x < (width>>2); x++)
+        {
+            WebRtc_Word32 avg = inPtr1[0] + inPtr2[0] + inPtr1[1] + inPtr2[1];
+            *outPtr= (WebRtc_UWord8)(avg >> 2);
+
+            inPtr1 += 2;
+            inPtr2 += 2;
+            outPtr++;
+        }
+        inPtr1 += (width >> 1);
+        inPtr2 += (width >> 1);
+    }
+    return height * (width >> 1) * 3;
+}
+
+WebRtc_Word32
+ScaleI420Up2(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8*& buffer,
+             WebRtc_UWord32 size, WebRtc_UWord32 &scaledWidth, WebRtc_UWord32 &scaledHeight)
+{
+    if (width <= 1 || height <= 1 || (width % 2) != 0 || (height % 2) != 0)
+    {
+        return -1;
+    }
+
+    if (size < (WebRtc_UWord32)(width * height * 3 / 2))
+    {
+        return -1;
+    }
+
+    scaledWidth  = (width << 1);
+    scaledHeight = (height << 1);
+
+    // Verify allocated size
+    WebRtc_UWord32 scaledBufferSize = CalcBufferSize(kI420, scaledWidth, scaledHeight);
+    VerifyAndAllocate(buffer, size, scaledBufferSize);
+    WebRtc_UWord8* inPtr1 = buffer + (3 * width * (height >> 1)) - 1;
+    WebRtc_UWord8* inPtr2 = buffer + (3 * width * (height >> 1)) - (width >> 1) - 1;
+    WebRtc_UWord8* outPtr1 = buffer + (3 * scaledWidth * (scaledHeight >> 1)) - 1;
+    WebRtc_UWord8* outPtr2 = buffer + (3 * scaledWidth * (scaledHeight >> 1)) - (scaledWidth >> 1) - 1;
+
+    // Color
+    for (WebRtc_Word32 i = 1; i <= 2; i++)
+    {
+        for (WebRtc_UWord32 y = 0; y < (height >> 1) - 1; y++)
+        {
+            for (WebRtc_UWord32 x = 0; x < (width >> 1) - 1; x++)
+            {
+                  *outPtr1 = *inPtr1;
+                  *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+                  inPtr1--;
+                  inPtr2--;
+                  outPtr1--;
+                  outPtr2--;
+                  *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+                  *outPtr2 = ((inPtr1[0] + inPtr1[1] + inPtr2[0] + inPtr2[1]) >> 2);
+                  outPtr1--;
+                  outPtr2--;
+            }
+            *outPtr1 = *inPtr1;
+            *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+            outPtr1--;
+            outPtr2--;
+            *outPtr1 = *inPtr1;
+            *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+            outPtr1--;
+            outPtr2--;
+            inPtr1--;
+            inPtr2--;
+            outPtr1 -= width;
+            outPtr2 -= width;
+        }
+        // First row
+        for (WebRtc_UWord32 x = 0; x < (width >> 1) - 1; x++)
+        {
+            *outPtr1 = *inPtr1;
+            *outPtr2 = *outPtr1;
+            inPtr1--;
+            inPtr2--;
+            outPtr1--;
+            outPtr2--;
+            *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+            *outPtr2 = *outPtr1;
+            outPtr1--;
+            outPtr2--;
+        }
+        *outPtr1 = *inPtr1;
+        *outPtr2 = *inPtr1;
+        outPtr1--;
+        outPtr2--;
+        *outPtr1 = *inPtr1;
+        *outPtr2 = *inPtr1;
+        outPtr1--;
+        outPtr2--;
+        inPtr1--;
+        inPtr2--;
+        outPtr1 -= width;
+        outPtr2 -= width;
+    }
+
+    inPtr2 -= (width >> 1);
+    outPtr2 -= width;
+
+    // illum
+    for (WebRtc_UWord32 y = 0; y < height - 1; y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < width - 1; x++)
+        {
+            *outPtr1 = *inPtr1;
+            *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+            inPtr1--;
+            inPtr2--;
+            outPtr1--;
+            outPtr2--;
+            *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+            *outPtr2 = ((inPtr1[0] + inPtr1[1] + inPtr2[0] + inPtr2[1]) >> 2);
+            outPtr1--;
+            outPtr2--;
+        }
+        *outPtr1 = *inPtr1;
+        *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+        outPtr1--;
+        outPtr2--;
+        *outPtr1 = *inPtr1;
+        *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+        outPtr1--;
+        outPtr2--;
+        inPtr1--;
+        inPtr2--;
+
+        outPtr1 -= scaledWidth;
+        outPtr2 -= scaledWidth;
+    }
+    // First row
+    for (WebRtc_UWord32 x = 0; x < width - 1; x++)
+    {
+        *outPtr1 = *inPtr1;
+        *outPtr2 = *outPtr1;
+        inPtr1--;
+        outPtr1--;
+        outPtr2--;
+        *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+        *outPtr2 = *outPtr1;
+        outPtr1--;
+        outPtr2--;
+    }
+    *outPtr1 = *inPtr1;
+    *outPtr2 = *inPtr1;
+    outPtr1--;
+    outPtr2--;
+    *outPtr1 = *inPtr1;
+    *outPtr2 = *inPtr1;
+
+    return scaledHeight * (scaledWidth >> 1) * 3;
+}
+
+WebRtc_Word32
+ScaleI420Up3_2(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8*& buffer,
+               WebRtc_UWord32 size, WebRtc_UWord32 &scaledWidth, WebRtc_UWord32 &scaledHeight)
+{
+    if (width <= 1 || height <= 1)
+    {
+        return -1;
+    }
+
+    if ((width % 2) != 0 || (height % 2) != 0 || ((width >> 1) % 2) != 0 || ((height >> 1) % 2) != 0)
+    {
+        return -1;
+    }
+
+    if (size < (WebRtc_UWord32)(width * height * 3 / 2))
+    {
+        return -1;
+    }
+
+    scaledWidth = 3 * (width >> 1);
+    scaledHeight = 3 * (height >> 1);
+
+    // Verify new buffer size
+    WebRtc_UWord32 scaledBufferSize = webrtc::CalcBufferSize(kI420, scaledWidth, scaledHeight);
+    VerifyAndAllocate(buffer, size, scaledBufferSize);
+
+    WebRtc_UWord8* inPtr1 = buffer + (3 * width * (height >> 1)) - 1;
+    WebRtc_UWord8* inPtr2 = buffer + (3 * width*(height >> 1)) - (width >> 1) - 1;
+
+    WebRtc_UWord8* outPtr1 = buffer + (3 * scaledWidth * (scaledHeight >> 1)) - 1;
+    WebRtc_UWord8* outPtr2 = buffer + (3 * scaledWidth * (scaledHeight >> 1)) - (scaledWidth >> 1) - 1;
+
+    WebRtc_Word32 cy = 0;
+    WebRtc_Word32 cx = 0;
+    // Color
+    for (WebRtc_UWord32 y = 0; y < (height); y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < (width >> 1); x++)
+        {
+            *outPtr1 = *inPtr1;
+            outPtr1--;
+            cy = y % 2;
+            cx = x % 2;
+            if (cy == 0)
+            {
+                *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+            }
+            outPtr2--;
+            inPtr1--;
+            inPtr2--;
+
+            if (cx == 0 && cy == 0)
+            {
+                *outPtr2 = ((inPtr1[0] + inPtr1[1] + inPtr2[0] + inPtr2[1]) >> 2);
+            }
+            if (cx == 0)
+            {
+                *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+                outPtr1--;
+                outPtr2--;
+            }
+        }
+        if (cy == 0)
+        {
+            outPtr1 -= (scaledWidth >> 1);
+            outPtr2 -= (scaledWidth >> 1);
+        }
+    }
+    inPtr2 -= (width >> 1);
+    outPtr2 -= (scaledWidth >> 1);
+
+    // illum
+    for (WebRtc_UWord32 y = 0; y < height; y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < width; x++)
+        {
+            *outPtr1 = *inPtr1;
+            outPtr1--;
+            cy = y % 2;
+            cx = x % 2;
+            if (cy == 0)
+            {
+                *outPtr2 = ((inPtr1[0] + inPtr2[0]) >> 1);
+            }
+            outPtr2--;
+            inPtr1--;
+            inPtr2--;
+            if (cx == 0 && cy == 0)
+            {
+                *outPtr2 = ((inPtr1[0] + inPtr1[1] + inPtr2[0] + inPtr2[1]) >> 2);
+            }
+            if (cx == 0)
+            {
+                *outPtr1 = ((inPtr1[0] + inPtr1[1]) >> 1);
+                outPtr1--;
+                outPtr2--;
+            }
+        }
+        if (cy == 0)
+        {
+            outPtr1 -= scaledWidth;
+            outPtr2 -= scaledWidth;
+        }
+    }
+
+    return scaledHeight * (scaledWidth >> 1) * 3;
+}
+
+WebRtc_Word32
+ScaleI420Down1_3(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord8*& buffer,
+                 WebRtc_UWord32 size, WebRtc_UWord32 &scaledWidth,
+                 WebRtc_UWord32 &scaledHeight)
+{
+    if (width <= 5 || height <= 5)
+    {
+        return -1;
+    }
+
+    if ((width % 2) != 0 || (height % 2) != 0 || (((height / 3) % 2) != 0))
+    {
+        return -1;
+    }
+
+    if (size < (WebRtc_UWord32)(width * height * 3 / 2))
+    {
+        return -1;
+    }
+
+    scaledWidth = width / 3;
+    scaledHeight = height / 3;
+    WebRtc_Word32 scaledBufferSize = CalcBufferSize(kI420, scaledWidth, scaledHeight);
+    VerifyAndAllocate(buffer, size, scaledBufferSize);
+
+    WebRtc_UWord8* inPtr1 = buffer;
+    WebRtc_UWord8* inPtr2 = buffer + width;
+    WebRtc_UWord8* outPtr = buffer;
+
+    WebRtc_Word32 remWidth = width - scaledWidth * 3;
+
+    bool addWidth = false;
+    if (scaledWidth % 2)
+    {
+        scaledWidth++;
+        addWidth = true;
+    }
+    WebRtc_Word32 remWidthCol = (width >> 1) - WebRtc_Word32((scaledWidth >> 1) * 3.0);
+
+    // illum
+    for (WebRtc_UWord32 y = 0; y < height / 3; y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < width / 3; x++)
+        {
+            *outPtr = ((inPtr1[0] + inPtr2[0] + inPtr1[1] + inPtr2[1]) >> 2);
+            inPtr1 += 3;
+            inPtr2 += 3;
+            outPtr++;
+        }
+        if (addWidth)
+        {
+            *outPtr = ((inPtr1[0] + inPtr2[0]) >> 1);
+            outPtr++;
+        }
+            inPtr1 += (width << 1) + remWidth;
+            inPtr2 += (width << 1) + remWidth;
+    }
+    inPtr1 = buffer + (width * height);
+    inPtr2 = inPtr1 + (width >> 1);
+
+    // Color
+    for (WebRtc_UWord32 y = 0; y < (scaledHeight >> 1); y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < (scaledWidth >> 1); x++)
+        {
+            *outPtr = ((inPtr1[0] + inPtr2[0] + inPtr1[1] + inPtr2[1]) >> 2);
+            inPtr1 += 3;
+            inPtr2 += 3;
+            outPtr++;
+        }
+        inPtr1 += width + (remWidthCol);
+        inPtr2 += width + (remWidthCol);
+    }
+    inPtr1 = buffer + (width * height) + (width * height >> 2);
+    inPtr2 = inPtr1 + (width >> 1);
+
+    for (WebRtc_UWord32 y = 0; y < (scaledHeight >> 1); y++)
+    {
+        for (WebRtc_UWord32 x = 0; x < (scaledWidth >> 1); x++)
+        {
+            *outPtr = ((inPtr1[0] + inPtr2[0] + inPtr1[1] + inPtr2[1]) >> 2);
+            inPtr1 += 3;
+            inPtr2 += 3;
+            outPtr++;
+        }
+        inPtr1 += width + (remWidthCol);
+        inPtr2 += width + (remWidthCol);
+    }
+
+    return scaledHeight * (scaledWidth >> 1) * 3;
+}
+
+
+WebRtc_Word32
+ConvertToI420(VideoType incomingVideoType,
+              const WebRtc_UWord8* incomingBuffer,
+              WebRtc_UWord32 width,
+              WebRtc_UWord32 height,
+              WebRtc_UWord8* outgoingBuffer,
+              bool interlaced /* =false */,
+              VideoRotationMode rotate /* =  kRotateNone  */)
+
+{
+    if (width < 1  || height < 1 )
+    {
+        return -1;
+    }
+    WebRtc_Word32 outgoingLength = 0;
+    WebRtc_Word32 length = 0;
+    switch(incomingVideoType)
+    {
+        case kRGB24:
+            outgoingLength = ConvertRGB24ToI420(width, height, incomingBuffer, outgoingBuffer);
+            break;
+        case kRGB565:
+            outgoingLength = ConvertRGB565ToI420(incomingBuffer, width, height, outgoingBuffer);
+            break;
+#ifdef WEBRTC_MAC
+        case kARGB:
+            outgoingLength = ConvertARGBMacToI420(width, height, incomingBuffer, outgoingBuffer);
+            break;
+#endif
+        case kI420:
+            switch(rotate)
+            {
+              case kRotateNone:
+                  length = CalcBufferSize(kI420, width, height);
+                  outgoingLength = length;
+                  memcpy(outgoingBuffer, incomingBuffer, length);
+                  break;
+              case kRotateClockwise:
+                  outgoingLength = ConvertToI420AndRotateClockwise(incomingBuffer, width,
+                                                                   height, outgoingBuffer,
+                                                                   height, width, kI420);
+                  break;
+              case kRotateAntiClockwise:
+                  outgoingLength = ConvertToI420AndRotateAntiClockwise(incomingBuffer, width,
+                                                                       height, outgoingBuffer,
+                                                                       height, width, kI420);
+                  break;
+              case kRotate180:
+                  outgoingLength = ConvertToI420AndMirrorUpDown(incomingBuffer,outgoingBuffer,
+                                                                width, height, kI420);
+                  break;
+              default:
+                  assert(false);
+                  break;
+            }
+            break;
+        case kYUY2:
+            if (interlaced) {
+                outgoingLength = ConvertYUY2ToI420interlaced(incomingBuffer, width, height,
+                                                             outgoingBuffer, width, height);
+            } else {
+                outgoingLength = ConvertYUY2ToI420(incomingBuffer, width, height,
+                                                   outgoingBuffer, width, height);
+            }
+            break;
+        case kUYVY:
+            if (interlaced) {
+                outgoingLength = ConvertUYVYToI420interlaced(incomingBuffer, width, height,
+                                                             outgoingBuffer, width, height);
+            } else {
+                outgoingLength = ConvertUYVYToI420(width, height, incomingBuffer,
+                                                   outgoingBuffer);
+            }
+            break;
+        case kYV12:
+            switch(rotate)
+                {
+                    case kRotateNone:
+                        outgoingLength = ConvertYV12ToI420(incomingBuffer, width, height,
+                                                           outgoingBuffer);
+                        break;
+                    case kRotateClockwise:
+                        outgoingLength = ConvertToI420AndRotateClockwise(incomingBuffer, width,
+                                                                         height, outgoingBuffer,
+                                                                         height,width, kYV12);
+                        break;
+                    case kRotateAntiClockwise:
+                        outgoingLength = ConvertToI420AndRotateAntiClockwise(incomingBuffer,
+                                                                             width, height,
+                                                                             outgoingBuffer,
+                                                                             height, width,
+                                                                             kYV12);
+                        break;
+                    case kRotate180:
+                        outgoingLength = ConvertToI420AndMirrorUpDown(incomingBuffer,
+                                                                      outgoingBuffer,
+                                                                      width, height, kYV12);
+                        break;
+                    default:
+                        assert(false);
+                        break;
+                }
+            break;
+        case kNV12:
+            switch(rotate)
+            {
+                case kRotateNone:
+                    outgoingLength = ConvertNV12ToI420(incomingBuffer, outgoingBuffer, width,
+                                                       height);
+                    break;
+                case kRotateClockwise:
+                    outgoingLength = ConvertNV12ToI420AndRotateClockwise(incomingBuffer,
+                                                                         outgoingBuffer,
+                                                                         width, height);
+                    break;
+                case kRotateAntiClockwise:
+                    outgoingLength = ConvertNV12ToI420AndRotateAntiClockwise(incomingBuffer,
+                                                                             outgoingBuffer,
+                                                                             width, height);
+                    break;
+                case kRotate180:
+                    outgoingLength = ConvertNV12ToI420AndRotate180(incomingBuffer,
+                                                                   outgoingBuffer,
+                                                                   width, height);
+                    break;
+                default:
+                    assert(false);
+                    break;
+            }
+            break;
+        case kNV21:
+            switch(rotate)
+            {
+                case kRotateNone:
+                    outgoingLength = ConvertNV21ToI420(incomingBuffer, outgoingBuffer, width,
+                                                       height);
+                    break;
+                case kRotateClockwise:
+                    outgoingLength = ConvertNV21ToI420AndRotateClockwise(incomingBuffer,
+                                                                         outgoingBuffer,
+                                                                         width, height);
+                    break;
+                case kRotateAntiClockwise:
+                    outgoingLength = ConvertNV21ToI420AndRotateAntiClockwise(incomingBuffer,
+                                                                             outgoingBuffer,
+                                                                             width, height);
+                    break;
+                case kRotate180:
+                    outgoingLength = ConvertNV21ToI420AndRotate180(incomingBuffer,
+                                                                   outgoingBuffer,
+                                                                   width, height);
+                    break;
+                default:
+                    assert(false);
+                    break;
+            }
+            break;
+        default:
+            assert(false);
+            break;
+    }
+    return outgoingLength;
+}
+
+WebRtc_Word32 ConvertFromI420(VideoType outgoingVideoType,
+                               const WebRtc_UWord8* incomingBuffer,
+                               WebRtc_UWord32 width,
+                               WebRtc_UWord32 height,
+                               WebRtc_UWord8* outgoingBuffer,
+                               bool interlaced /* = false */,
+                               VideoRotationMode rotate /* = kRotateNone */)
+
+{
+    if (width < 1  || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_Word32 outgoingLength = 0;
+    WebRtc_Word32 length = 0;
+    switch(outgoingVideoType)
+    {
+      case kRGB24:
+          outgoingLength = ConvertI420ToRGB24(incomingBuffer, outgoingBuffer, width, height);
+          break;
+      case kARGB:
+         outgoingLength = ConvertI420ToARGB(incomingBuffer, outgoingBuffer, width, height, 0);
+         break;
+      case kARGB4444:
+          outgoingLength = ConvertI420ToARGB4444(incomingBuffer, outgoingBuffer, width, height, 0);
+          break;
+      case kARGB1555:
+          outgoingLength = ConvertI420ToARGB1555(incomingBuffer, outgoingBuffer, width, height,0);
+          break;
+      case kRGB565:
+          outgoingLength = ConvertI420ToRGB565(incomingBuffer, outgoingBuffer, width, height);
+          break;
+      case kI420:
+          length = CalcBufferSize(kI420, width, height);
+          outgoingLength = length;
+          memcpy(outgoingBuffer, incomingBuffer, length);
+          break;
+      case kUYVY:
+          outgoingLength = ConvertI420ToUYVY(incomingBuffer, outgoingBuffer, width, height);
+          break;
+      case kYUY2:
+          outgoingLength = ConvertI420ToYUY2(incomingBuffer, outgoingBuffer, width, height,0);
+          break;
+      case kYV12:
+        outgoingLength = ConvertI420ToYV12(incomingBuffer, outgoingBuffer, width, height,0);
+        break;
+#ifdef WEBRTC_MAC
+      case kRGBAMac:
+        outgoingLength = ConvertI420ToRGBAMac(incomingBuffer, outgoingBuffer, width, height,0);
+        break;
+      case kARGBMac:
+        outgoingLength = ConvertI420ToARGBMac(incomingBuffer, outgoingBuffer, width, height,0);
+        break;
+#endif
+      default:
+          assert(false);
+          break;
+    }
+    return outgoingLength;
+}
+
+WebRtc_Word32
+MirrorI420LeftRight( const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                     WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+
+    WebRtc_Word32 indO = 0;
+    WebRtc_Word32 indS  = 0;
+    WebRtc_UWord32 wind, hind;
+    WebRtc_UWord8 tmpVal;
+    // will swap two values per iteration
+    const WebRtc_UWord32 halfW = width >> 1;
+    // Y
+    for (wind = 0; wind < halfW; wind++ )
+    {
+        for (hind = 0; hind < height; hind++ )
+        {
+            indO = hind * width + wind;
+            indS = hind * width + (width - wind - 1); // swapping index
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        } // end for (height)
+    } // end for(width)
+    const WebRtc_UWord32 lengthW = width >> 2;
+    const WebRtc_UWord32 lengthH = height >> 1;
+    // V
+    WebRtc_Word32 zeroInd = width * height;
+    for (wind = 0; wind < lengthW; wind++ )
+    {
+        for (hind = 0; hind < lengthH; hind++ )
+        {
+            indO = zeroInd + hind * halfW + wind;
+            indS = zeroInd + hind * halfW + (halfW - wind - 1); // swapping index
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        } // end for (height)
+    } // end for(width)
+
+    //U
+    zeroInd += width * height >> 2;
+    for (wind = 0; wind < lengthW; wind++ )
+    {
+        for (hind = 0; hind < lengthH; hind++ )
+        {
+            indO = zeroInd + hind * halfW + wind;
+            indS = zeroInd + hind * halfW + (halfW - wind - 1); // swapping index
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        } // end for (height)
+    } // end for(width)
+
+    return 0;
+}
+
+WebRtc_Word32
+MirrorI420UpDown( const WebRtc_UWord8* inFrame, WebRtc_UWord8* outFrame,
+                  WebRtc_UWord32 width, WebRtc_UWord32 height)
+{
+    if (width < 1 || height < 1)
+    {
+        return -1;
+    }
+    WebRtc_UWord32 indO = 0;
+    WebRtc_UWord32 indS  = 0;
+    WebRtc_UWord32 wind, hind;
+    WebRtc_UWord8 tmpVal;
+    WebRtc_UWord32 halfH = height >> 1;
+    WebRtc_UWord32 halfW = width >> 1;
+    // Y
+    for (hind = 0; hind < halfH; hind++ )
+    {
+        for (wind = 0; wind < width; wind++ )
+        {
+            indO = hind * width + wind;
+            indS = (height - hind - 1) * width + wind;
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        }
+    }
+    // V
+    WebRtc_UWord32 lengthW = width >> 1;
+    WebRtc_UWord32 lengthH = height >> 2;
+    WebRtc_UWord32 zeroInd = width * height;
+    for (hind = 0; hind < lengthH; hind++ )
+    {
+        for (wind = 0; wind < lengthW; wind++ )
+        {
+            indO = zeroInd + hind * halfW + wind;
+            indS = zeroInd + (halfH - hind - 1) * halfW + wind;
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        }
+    }
+    // U
+    zeroInd += width * height >> 2;
+    for (hind = 0; hind < lengthH; hind++ )
+    {
+        for (wind = 0; wind < lengthW; wind++ )
+        {
+            indO = zeroInd + hind * halfW + wind;
+            indS = zeroInd + (halfH - hind - 1) * halfW + wind;
+            tmpVal = inFrame[indO];
+            outFrame[indO] = inFrame[indS];
+            outFrame[indS] = tmpVal;
+        }
+    }
+    return 0;
+}
+
+WebRtc_Word32
+ConvertToI420AndMirrorUpDown(const WebRtc_UWord8* srcBuffer, WebRtc_UWord8* dstBuffer,
+                             WebRtc_UWord32 srcWidth, WebRtc_UWord32 srcHeight,
+                             VideoType colorSpaceIn)
+{
+    if (colorSpaceIn != kI420 && colorSpaceIn != kYV12)
+    {
+        return -1;
+    }
+
+    const WebRtc_Word32 sourceHeight = srcHeight;
+    const WebRtc_Word32 halfHeight = srcHeight >> 1;
+    const WebRtc_Word32 sourceWidth = srcWidth;
+    const WebRtc_Word32 halfWidth = sourceWidth >> 1;
+    WebRtc_UWord8* targetBuffer = dstBuffer;
+    const WebRtc_UWord8* sourcePtr = srcBuffer;
+
+    //Mirror Y component
+    for (WebRtc_UWord32 newRow = 0; newRow < srcHeight; ++newRow)
+    {
+        memcpy(targetBuffer, &sourcePtr[((srcHeight - newRow) - 1) * sourceWidth], sourceWidth);
+        targetBuffer += sourceWidth;
+    }
+
+    //Mirror U component
+    sourcePtr += sourceHeight * sourceWidth;
+    if (colorSpaceIn == kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    }
+    for (WebRtc_Word32 newRow = 0; newRow < halfHeight; ++newRow)
+    {
+        memcpy(targetBuffer, &sourcePtr[((halfHeight - newRow) - 1) * halfWidth], halfWidth);
+        targetBuffer += halfWidth;
+    }
+
+    //Mirror V component
+    if (colorSpaceIn != kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    }
+    else
+    {
+        sourcePtr -= (sourceHeight * sourceWidth) >> 2;
+    }
+    for(WebRtc_Word32 newRow = 0; newRow < halfHeight; ++newRow)
+    {
+        memcpy(targetBuffer, &sourcePtr[((halfHeight - newRow) - 1) * halfWidth], halfWidth);
+        targetBuffer += halfWidth;
+    }
+    return 0;
+}
+
+
+WebRtc_Word32
+ConvertToI420AndRotateClockwise(const WebRtc_UWord8* srcBuffer, WebRtc_UWord32 srcWidth,
+                                WebRtc_UWord32 srcHeight, WebRtc_UWord8* dstBuffer,
+                                WebRtc_UWord32 dstWidth, WebRtc_UWord32 dstHeight,
+                                VideoType colorSpaceIn)
+{
+    if (colorSpaceIn != kI420 && colorSpaceIn != kYV12)
+    {
+         return -1;
+     }
+
+    const WebRtc_Word32 targetHeight = dstHeight;
+    const WebRtc_Word32 targetWidth = dstWidth;
+    const WebRtc_Word32 sourceHeight = srcHeight;
+    const WebRtc_Word32 sourceWidth = srcWidth;
+
+    WebRtc_UWord8* targetBuffer=dstBuffer;
+    const WebRtc_UWord8* sourcePtr=srcBuffer;
+
+    // Paint the destination buffer black
+    memset(dstBuffer,0,dstWidth * dstHeight);
+    memset(dstBuffer + dstWidth * dstHeight,127,(dstWidth * dstHeight) / 2);
+
+    const WebRtc_Word32 paddingWidth = (targetWidth - sourceHeight) / 2;
+    const WebRtc_Word32 halfPaddingWidth = paddingWidth / 2;
+    const WebRtc_Word32 paddingHeight = (targetHeight - sourceWidth) / 2;
+    const WebRtc_Word32 halfPaddingHeight = paddingHeight / 2;
+
+    //Rotate Y component
+    targetBuffer += paddingHeight * targetWidth;
+    for(WebRtc_Word32 newRow = 0; newRow < sourceWidth; ++newRow)
+    {
+        targetBuffer+=paddingWidth;
+        for(WebRtc_Word32 newColumn = sourceHeight - 1;newColumn >= 0;--newColumn)
+        {
+            (*targetBuffer++) = sourcePtr[newColumn * sourceWidth + newRow];
+        }
+        targetBuffer += paddingWidth;
+    }
+    targetBuffer += paddingHeight * targetWidth;
+
+    //Rotate U component and store as kI420
+    sourcePtr += sourceHeight * sourceWidth;
+    if (colorSpaceIn == kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    for(WebRtc_Word32 newRow = 0;newRow < sourceWidth / 2; ++newRow)
+    {
+        targetBuffer += halfPaddingWidth;
+        for(WebRtc_Word32 newColumn=sourceHeight / 2 - 1; newColumn >= 0; --newColumn)
+        {
+            (*targetBuffer++) = sourcePtr[(newColumn * sourceWidth >> 1) + newRow];
+        }
+        targetBuffer += halfPaddingWidth;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+
+    //Rotate V component
+    if (colorSpaceIn != kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    } else
+    {
+        sourcePtr -= (sourceHeight * sourceWidth) >> 2;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    for(WebRtc_Word32 newRow = 0; newRow < sourceWidth / 2; ++newRow)
+    {
+        targetBuffer+=halfPaddingWidth;
+        for(WebRtc_Word32 newColumn = sourceHeight / 2 - 1; newColumn >= 0; --newColumn)
+        {
+            (*targetBuffer++) = sourcePtr[(newColumn * sourceWidth >> 1) + newRow];
+        }
+        targetBuffer += halfPaddingWidth;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    return 0;
+}
+
+
+WebRtc_Word32
+ConvertToI420AndRotateAntiClockwise(const WebRtc_UWord8* srcBuffer, WebRtc_UWord32 srcWidth,
+                                    WebRtc_UWord32 srcHeight, WebRtc_UWord8* dstBuffer,
+                                    WebRtc_UWord32 dstWidth, WebRtc_UWord32 dstHeight,
+                                    VideoType colorSpaceIn)
+{
+    if (colorSpaceIn != kI420 && colorSpaceIn != kYV12)
+    {
+        return -1;
+    }
+    if (dstWidth < srcHeight || dstHeight < srcWidth)
+    {
+        return -1;
+    }
+    const WebRtc_Word32 targetHeight = dstHeight;
+    const WebRtc_Word32 targetWidth = dstWidth;
+    const WebRtc_Word32 sourceHeight = srcHeight;
+    const WebRtc_Word32 sourceWidth = srcWidth;
+
+    WebRtc_UWord8* targetBuffer = dstBuffer;
+
+    const WebRtc_UWord8* sourcePtr = srcBuffer;
+
+    // Paint the destination buffer black
+    memset(dstBuffer,0,dstWidth * dstHeight);
+    memset(dstBuffer + dstWidth * dstHeight,127,(dstWidth * dstHeight) / 2);
+
+    const WebRtc_Word32 paddingWidth = (targetWidth - sourceHeight) / 2;
+    const WebRtc_Word32 halfPaddingWidth = paddingWidth / 2;
+
+    const WebRtc_Word32 paddingHeight = (targetHeight - sourceWidth) / 2;
+    const WebRtc_Word32 halfPaddingHeight = paddingHeight / 2;
+
+    //Rotate Y component
+    targetBuffer += paddingHeight*targetWidth;
+    for(WebRtc_Word32 newRow = sourceWidth - 1; newRow >= 0; --newRow)
+    {
+        targetBuffer+=paddingWidth;
+         for(WebRtc_Word32 newColumn = 0; newColumn < sourceHeight; ++newColumn)
+         {
+             (*targetBuffer++) = sourcePtr[newColumn * sourceWidth + newRow];
+         }
+         targetBuffer += paddingWidth;
+    }
+    targetBuffer += paddingHeight * targetWidth;
+
+    //Rotate U component and store as kI420
+    sourcePtr += sourceHeight * sourceWidth;
+    if (colorSpaceIn == kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    for(WebRtc_Word32 newRow = sourceWidth / 2 - 1; newRow >= 0;--newRow)
+    {
+        targetBuffer += halfPaddingWidth;
+        for(WebRtc_Word32 newColumn = 0; newColumn < sourceHeight / 2; ++newColumn)
+        {
+            (*targetBuffer++) = sourcePtr[(newColumn*sourceWidth >> 1) + newRow];
+        }
+        targetBuffer += halfPaddingWidth;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+
+    //Rotate V component
+    if (colorSpaceIn != kYV12)
+    {
+        sourcePtr += (sourceHeight * sourceWidth) >> 2;
+    } else
+    {
+        sourcePtr -= (sourceHeight * sourceWidth) >> 2;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    for (WebRtc_Word32 newRow = sourceWidth / 2 - 1; newRow >= 0; --newRow)
+    {
+        targetBuffer += halfPaddingWidth;
+        for (WebRtc_Word32 newColumn = 0; newColumn < sourceHeight / 2; ++newColumn)
+        {
+            (*targetBuffer++) = sourcePtr[(newColumn*sourceWidth >> 1) + newRow];
+        }
+        targetBuffer += halfPaddingWidth;
+    }
+    targetBuffer += halfPaddingHeight * targetWidth / 2;
+    return 0;
+}
+
+
+inline
+WebRtc_UWord8 Clip(WebRtc_Word32 val)
+{
+    if (val < 0)
+    {
+        return (WebRtc_UWord8)0;
+    } else if (val > 255)
+    {
+        return (WebRtc_UWord8)255;
+    }
+    return (WebRtc_UWord8)val;
+}
+
+WebRtc_Word32
+VerifyAndAllocate(WebRtc_UWord8*& buffer, WebRtc_UWord32 currentSize, WebRtc_UWord32 newSize)
+{
+    if (newSize > currentSize)
+    {
+        // make sure that our buffer is big enough
+        WebRtc_UWord8* newBuffer = new WebRtc_UWord8[newSize];
+        if (buffer)
+        {
+            // copy old data
+            memcpy(newBuffer, buffer, currentSize);
+            delete [] buffer;
+        }
+        buffer = newBuffer;
+        return newSize;
+    }
+    return currentSize;
+}
+
+#ifdef SCALEOPT
+//memcpy_16 assumes that width is an integer multiple of 16!
+void *memcpy_16(void * dest, const void * src, size_t n)
+{
+    _asm
+    {
+        mov eax, dword ptr [src]
+        mov ebx, dword ptr [dest]
+        mov ecx, dword ptr [n]
+
+    loop0:
+
+        movdqu    xmm0, XMMWORD PTR [eax]
+        movdqu    XMMWORD PTR [ebx], xmm0
+        add       eax, 16
+        add       ebx, 16
+        sub       ecx, 16
+        jg        loop0
+    }
+}
+
+//memcpy_8 assumes that width is an integer multiple of 8!
+void *memcpy_8(void * dest, const void * src, size_t n)
+{
+    _asm
+    {
+        mov eax, dword ptr [src]
+        mov ebx, dword ptr [dest]
+        mov ecx, dword ptr [n]
+
+    loop0:
+
+        movq    mm0, QWORD PTR [eax]
+        movq    QWORD PTR [ebx], mm0
+        add       eax, 8
+        add       ebx, 8
+        sub       ecx, 8
+        jg        loop0
+
+    emms
+    }
+
+}
+
+#endif
+
+}
diff --git a/common_video/vplib/main/source/vplib.gyp b/common_video/vplib/main/source/vplib.gyp
new file mode 100644
index 0000000..e21a503
--- /dev/null
+++ b/common_video/vplib/main/source/vplib.gyp
@@ -0,0 +1,71 @@
+# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+  'includes': [
+    '../../../../common_settings.gypi', # Common settings
+  ],
+  'targets': [
+    {
+      'target_name': 'webrtc_vplib',
+      'type': '<(library)',
+      'dependencies': [
+      ],
+      'include_dirs': [
+        '../interface',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../interface',
+        ],
+      },
+      'sources': [
+        # interfaces
+        '../interface/vplib.h',
+        '../interface/interpolator.h',
+
+        # headers
+        'conversion_tables.h',
+        'scale_bilinear_yuv.h',
+      
+        # sources
+        'vplib.cc',
+        'interpolator.cc',
+        'scale_bilinear_yuv.cc',
+      ],
+    },
+    {
+      'target_name': 'vplib_test',
+      'type': 'executable',
+      'dependencies': [
+        'webrtc_vplib',
+      ],
+      'include_dirs': [
+         '../interface',
+         '../source',
+      ],
+      'sources': [
+
+        # headers
+        '../test/test_util.h',
+        
+        # sources
+        '../test/tester_main.cc',
+        '../test/scale_test.cc',
+        '../test/convert_test.cc',
+        '../test/interpolation_test.cc',
+      ], # source
+    },  
+  ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/common_video/vplib/main/test/convert_test.cc b/common_video/vplib/main/test/convert_test.cc
new file mode 100644
index 0000000..dec535d
--- /dev/null
+++ b/common_video/vplib/main/test/convert_test.cc
@@ -0,0 +1,368 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// Test application for color space conversion functions
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+#include <cmath>
+#include <time.h>
+
+#include "test_util.h"
+#include "vplib.h"
+
+using namespace webrtc;
+
+
+// Optimization testing
+//#define SCALEOPT //For Windows currently, June 2010
+
+WebRtc_Word32
+ImagePSNRfromBuffer(WebRtc_UWord8 *refBufName, WebRtc_UWord8 *testBufName,
+                    WebRtc_Word32 width, WebRtc_Word32 height,
+                    VideoType vType, double *YPSNRptr);
+void TestRetVal(int testVal, int refVal );
+
+int  convert_test(CmdArgs& args)
+{
+    // reading YUV frame - testing on the first frame of the foreman sequence
+    
+    //SET UP
+    int j = 0;
+    int retVal;
+    std::string outname = args.outputFile;
+    if (outname == "")
+    {
+        outname = "conversionTest_out.yuv";
+    }
+    std::string inname;
+    inname = args.inputFile;
+    FILE* sourceFile;
+    FILE* outputFile;
+    FILE* logFile;
+    WebRtc_UWord32 width = args.width;
+    WebRtc_UWord32 height = args.height;
+    WebRtc_UWord32 lengthSourceFrame = width*height*3/2;
+    double psnr = 0;
+    if ((sourceFile = fopen(inname.c_str(), "rb")) == NULL)
+    {
+        printf("Cannot read file %s.\n", inname.c_str());
+        exit(1); 
+    }
+    if ((outputFile = fopen(outname.c_str(), "wb")) == NULL)
+    {
+        printf("Cannot write file %s.\n", outname.c_str());
+        exit(1);
+    }
+    if ((logFile = fopen("../log.txt", "a")) == NULL)
+    {
+        printf("Cannot write file ../log.txt.\n");
+        exit(1);
+    }
+
+    // reading first frame of Foreman sequence
+    WebRtc_UWord8* origBuffer = new WebRtc_UWord8[width * height*3/2];
+    fread(origBuffer, 1, lengthSourceFrame, sourceFile);
+
+    // START TEST
+    printf("\nTEST #%d I420 <-> RGB24\n", j);
+
+    WebRtc_UWord8* resRGBBuffer2  = new WebRtc_UWord8[width*height*3];
+    WebRtc_UWord8* resI420Buffer = new WebRtc_UWord8[width*height*3/2];
+    retVal = ConvertFromI420(kRGB24, origBuffer, width, height,resRGBBuffer2);
+    TestRetVal(retVal, width*height*3);
+    clock_t tticks = clock();
+    for (int tt = 0; tt < 1000; tt++)
+    {
+        retVal = ConvertToI420(kRGB24, resRGBBuffer2, width, height,
+                               resI420Buffer);
+    }
+    tticks = clock() - tticks;
+    printf("RGB24->I420 Time(1000): %d\n", tticks);
+
+    TestRetVal(retVal, width*height*3/2);
+    fwrite(resI420Buffer, lengthSourceFrame, 1, outputFile);
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height, kI420, &psnr);
+    printf("Conversion between type #%d and type #%d, PSNR = %f\n", kI420,
+           kRGB24, psnr);
+    j++;
+    delete [] resRGBBuffer2;
+
+
+    printf("\nTEST #%d I420 <-> UYVY\n", j);
+    WebRtc_UWord8* outUYVYBuffer = new WebRtc_UWord8[width*height*2];
+
+    clock_t ticks = clock();
+    for (int t = 0; t < 100; t++)
+    {
+        retVal = ConvertFromI420(kUYVY, origBuffer, width,
+                                 height, outUYVYBuffer);
+    }
+    ticks = clock() - ticks;
+#ifndef SCALEOPT
+    fprintf(logFile, "\nConvertI420ToUYVY, before opt: %d\n", ticks);
+#else
+    fprintf(logFile, "\nConvertI420ToUYVY, after opt: %d\n", ticks);
+#endif
+
+    TestRetVal(retVal, width*height*2);
+    retVal = ConvertToI420(kUYVY, outUYVYBuffer, width, height, resI420Buffer);
+    TestRetVal(retVal, width*height*3/2);
+
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height, kI420, &psnr);
+    printf("Conversion between type #%d and type #%d, PSNR = %f\n",
+           kI420, kUYVY, psnr);
+    j++;
+    delete [] outUYVYBuffer;
+
+
+    printf("\nTEST #%d I420 <-> I420 \n", j);
+
+    WebRtc_UWord8* outI420Buffer = new WebRtc_UWord8[width*height*2];
+    retVal = ConvertToI420(kI420, origBuffer, width, height, outI420Buffer);
+    TestRetVal(retVal, width*height*3/2);
+    retVal = ConvertToI420(kI420 ,outI420Buffer, width, height, resI420Buffer);
+    TestRetVal(retVal, width*height*3/2);
+    fwrite(resI420Buffer, lengthSourceFrame, 1, outputFile);
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height,
+                        kI420, &psnr);
+    printf("Conversion between type #%d and type #%d, PSNR = %f\n",
+           kI420, kUYVY, psnr);
+    j++;
+    delete [] outI420Buffer;
+
+    printf("\nTEST #%d I420 <-> YV12\n", j);
+    outI420Buffer = new WebRtc_UWord8[width*height*3/2]; // assuming DIFF = 0
+
+    ticks = clock();
+    for (int t = 0; t < 1000; t++)
+    {
+        retVal = ConvertFromI420(kYV12, origBuffer, width, height, outI420Buffer);
+    }
+    ticks = clock() - ticks;
+#ifndef SCALEOPT
+    fprintf(logFile, "\nConvertI420ToYV12, before opt: %d\n", ticks);
+#else
+    fprintf(logFile, "\nConvertI420ToYV12, after opt: %d\n", ticks);
+#endif
+    TestRetVal(retVal, width*height*3/2);
+    retVal = webrtc::ConvertYV12ToI420(outI420Buffer, width, height,
+                                       resI420Buffer);
+    TestRetVal(retVal, width*height*3/2);
+
+    fwrite(resI420Buffer, lengthSourceFrame, 1, outputFile);
+
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height, kI420, &psnr);
+    printf("Conversion between type #%d and type #%d, PSNR = %f\n", kI420,
+           kYV12, psnr);
+    j++;
+    delete [] outI420Buffer;
+    delete [] resI420Buffer;
+
+
+    printf("\nTEST #%d I420<-> RGB565\n", j);
+    WebRtc_UWord8* res2ByteBuffer = new WebRtc_UWord8[width*height*2];
+    resI420Buffer = new WebRtc_UWord8[width * height * 3 / 2];
+    retVal = ConvertFromI420(kRGB565, origBuffer, width, height, res2ByteBuffer);
+    TestRetVal(retVal, width*height*2);
+    retVal = ConvertRGB565ToI420(res2ByteBuffer, width, height, resI420Buffer);
+    TestRetVal(retVal, width*height*3/2);
+    fwrite(resI420Buffer, lengthSourceFrame, 1, outputFile);
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height, kI420, &psnr);
+    printf("Note: Frame was compressed!\n");
+    printf("Conversion between type #%d and type #%d, PSNR = %f\n", kI420,
+           kRGB565, psnr);
+ 
+    delete [] res2ByteBuffer;
+    j++;
+
+    printf("\nTEST #%d I420 <-> YUY2\n", j);
+    WebRtc_UWord8* outYUY2Buffer = new WebRtc_UWord8[width*height*2];
+
+    ticks = clock();
+    for (int t = 0; t < 1000; t++)
+    {
+        retVal = ConvertI420ToYUY2(origBuffer, outYUY2Buffer, width, height,0);
+    }
+    ticks = clock() - ticks;
+#ifndef SCALEOPT
+    fprintf(logFile, "\nConvertI420ToYUY2, before opt: %d\n", ticks);
+#else
+    fprintf(logFile, "\nConvertI420ToYUY2, after opt: %d\n", ticks);
+#endif
+    TestRetVal(retVal, width*height*2);
+    ticks = clock();
+    for (int t = 0; t < 1000; t++)
+    {
+        retVal = ConvertToI420(kYUY2, outYUY2Buffer, width, height,
+                               resI420Buffer);
+    }
+    ticks = clock() - ticks;
+#ifndef SCALEOPT
+    fprintf(logFile, "\nConvertYUY2ToI420, before opt: %d\n", ticks);
+#else
+    fprintf(logFile, "\nConvertYUY2ToI420, after opt: %d\n", ticks);
+#endif
+    TestRetVal(retVal, width*height*3/2);
+    fwrite(resI420Buffer, lengthSourceFrame, 1, outputFile);
+    ImagePSNRfromBuffer(origBuffer, resI420Buffer, width, height, kI420, &psnr);
+    printf("Conversion between type #%d and type #%d,PSNR = %f\n", kI420,
+           kYUY2, psnr);
+  
+    delete [] outYUY2Buffer;
+    j++;
+ 
+    printf("\nTEST #%d I420 <-> UYVY\n", j);
+
+    outUYVYBuffer = new WebRtc_UWord8[width*height*2]; // assuming DIFF = 0
+    WebRtc_UWord8* resYUVBuffer = new WebRtc_UWord8[width*height*2];
+    retVal = ConvertFromI420(kUYVY, origBuffer, width, height, outUYVYBuffer);
+    TestRetVal(retVal, width*height*2);
+    retVal = ConvertToI420(kUYVY, outUYVYBuffer, width, height, resYUVBuffer);
+    TestRetVal(retVal, width*height*3/2);
+    fwrite(resYUVBuffer, lengthSourceFrame, 1, outputFile);
+    ImagePSNRfromBuffer(origBuffer, resYUVBuffer, width, height, kI420, &psnr);
+    printf("Conversion between type #%d and type #%d,PSNR = %f\n", kI420,
+           kUYVY, psnr);
+
+    delete [] outUYVYBuffer;
+    delete [] resYUVBuffer;
+
+    j++;
+
+     /*******************************************************************
+     * THE FOLLOWING FUNCTIONS HAVE NO INVERSE, BUT ARE PART OF THE TEST
+     * IN ORDER TO VERIFY THAT THEY DO NOT CRASH
+     *******************************************************************/
+     printf("\n\n Running functions with no inverse...\n");
+
+     //printf("TEST #%d I420 -> ARGB4444 \n", j);
+     res2ByteBuffer  = new WebRtc_UWord8[width*height*2];
+     ConvertI420ToARGB4444(origBuffer, res2ByteBuffer, width, height, 0);
+     delete [] res2ByteBuffer;
+
+     // YUY2 conversions
+     //printf("TEST #%d I420 -> YUY2 \n", j);
+     WebRtc_UWord8* sourceYUY2 = new WebRtc_UWord8[width*height*2];
+     ConvertI420ToYUY2(origBuffer, sourceYUY2, width, height, 0);
+
+     delete [] sourceYUY2;
+
+     //UYVY conversions
+     WebRtc_UWord8* sourceUYVY = new WebRtc_UWord8[width*height*2];
+     ConvertI420ToUYVY(origBuffer, sourceUYVY, width, height, 0);
+
+     //printf("TEST I420-> ARGB444\n");
+     res2ByteBuffer  = new WebRtc_UWord8[(width+10)*height*2];
+     retVal = webrtc::ConvertI420ToARGB4444(origBuffer, res2ByteBuffer,
+                                            width, height, width + 10);
+     TestRetVal(retVal, (width+10)*height*2);
+     delete [] res2ByteBuffer;
+
+      //printf("TEST I420-> ARGB1555\n");
+     res2ByteBuffer  = new WebRtc_UWord8[(width+10)*height*2];
+     retVal = ConvertI420ToARGB1555(origBuffer, res2ByteBuffer, width,
+                                    height, width + 10);
+     TestRetVal(retVal, (width+10)*height*2);
+     delete [] res2ByteBuffer;
+
+     //printf("TEST NV12 - > I420\n");
+     // using original I420 sequence - > just to verify it doesn't crash
+     ConvertNV12ToI420(origBuffer,resI420Buffer, width, height);
+     //printf("TEST NV12 - > I420 and Rotate 180\n");
+     ConvertNV12ToI420AndRotate180(origBuffer, resI420Buffer, width, height);
+     //printf("TEST NV12 - > I420 and Rotate anti Clockwise\n");
+     ConvertNV12ToI420AndRotateAntiClockwise(origBuffer, resI420Buffer,
+                                             width, height);
+     //printf("TEST NV12 - > I420 and Rotate Clockwise\n");
+     ConvertNV12ToI420AndRotateClockwise(origBuffer, resI420Buffer,
+                                         width, height);
+     //printf("TEST NV12 -> RGB565 \n");
+     res2ByteBuffer  = new WebRtc_UWord8[(width+10)*height*2];
+     ConvertNV12ToRGB565(origBuffer, res2ByteBuffer, width, height);
+     delete [] res2ByteBuffer;
+
+     //printf("TEST I420 - > RGBAIPhone");
+     WebRtc_UWord8* resBuffer = new WebRtc_UWord8[(width + 10) * height * 4];
+     ConvertI420ToRGBAIPhone(origBuffer, resBuffer, width, height, width + 10);
+     delete [] resBuffer;
+
+     //printf("TEST #%d I420 <-> ARGB_Mac", j);
+     WebRtc_UWord8* outARGBBuffer = new WebRtc_UWord8[width * height * 4];
+     retVal = ConvertI420ToARGBMac(origBuffer,outARGBBuffer, width, height, 0);
+     TestRetVal(retVal, width * height * 4);
+     delete [] outARGBBuffer;
+
+
+
+
+    //closing
+    fclose(sourceFile);
+    fclose(outputFile);
+    fclose(logFile);
+    delete [] origBuffer;
+    delete [] resI420Buffer;
+    std::cout << "\n**  View output file **\n";
+    std::cout << "Press enter to  quit test...";
+    std::string str;
+    std::getline(std::cin, str);
+    
+    return 0;
+}
+
+WebRtc_Word32
+ImagePSNRfromBuffer(WebRtc_UWord8 *refBufName, WebRtc_UWord8 *testBufName,
+                    WebRtc_Word32 width, WebRtc_Word32 height,
+                    VideoType vType, double *YPSNRptr)
+{
+    // currently assumes I420
+    if (vType != kI420)
+    {
+        return -1;
+    }
+    double mse = 0.0;
+    double mseLogSum = 0.0;
+   
+    WebRtc_UWord8 *ref = refBufName;
+    WebRtc_UWord8 * test = testBufName;
+    // comparing only 1 frame
+    mse = 0.0;
+
+    // calculate Y sum-square-difference
+    for( int k = 0; k < width * height; k++ )
+    {
+          mse += (test[k] - ref[k]) * (test[k] - ref[k]);
+    }
+
+    // divide by number of pixels
+    mse /= (double) (width * height);
+
+    if (mse == 0)
+    {
+        *YPSNRptr = 48;
+        return 0;
+    }
+    // accumulate for total average
+    mseLogSum += std::log10( mse );
+   
+    *YPSNRptr = 20.0 * std::log10(255.0) - 10.0 * mseLogSum;
+
+     return 0;
+}
+
+void TestRetVal(int testVal, int refVal )
+{
+    if (testVal != refVal)
+    {
+        printf("return value = %d, desired value = %d\n", testVal, refVal);
+    }
+}
diff --git a/common_video/vplib/main/test/convert_test/convert_test.h b/common_video/vplib/main/test/convert_test/convert_test.h
new file mode 100644
index 0000000..992b497
--- /dev/null
+++ b/common_video/vplib/main/test/convert_test/convert_test.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_COMMON_VIDEO_VPLIB_TEST_CONVERT_TEST_H
+#define WEBRTC_COMMON_VIDEO_VPLIB_TEST_CONVERT_TEST_H
+
+#include "vplib.h"
+
+
+void ToFile(WebRtc_UWord8 *buf, WebRtc_Word32 length, WebRtc_Word32 num);
+WebRtc_Word32
+PSNRfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, WebRtc_Word32 width, 
+              WebRtc_Word32 height, WebRtc_Word32 numberOfFrames, double *YPSNRptr);
+
+#endif
diff --git a/common_video/vplib/main/test/interpolation_test.cc b/common_video/vplib/main/test/interpolation_test.cc
new file mode 100644
index 0000000..9ae1ce5
--- /dev/null
+++ b/common_video/vplib/main/test/interpolation_test.cc
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "interpolator.h"
+#include "vplib.h"
+#include "test_util.h"
+
+using namespace webrtc;
+
+int interpolationTest(CmdArgs& args)
+{
+    // Read input file, interpolate first frame according to requested method
+    // for now only YUV input and output
+
+    FILE* sourceFile;
+    FILE* outputFile;
+
+    std::string outname = args.outputFile;
+    if (outname == "")
+    {
+        outname = "InterTest_out.yuv";
+    }
+    if (args.width < 1 || args.height < 1 ||
+        args.dstWidth < 1 || args.dstHeight < 1)
+    {
+        printf("Error in input dimensions\n" );
+        return -1;
+    }
+
+    WebRtc_Word32 ret;
+
+    // create interpolator
+    webrtc::interpolator* inter = new webrtc::interpolator();
+    ret = inter->Set(args.width, args.height,
+                     args.dstWidth, args.dstHeight,
+                     kI420, kI420,
+                     (webrtc::interpolatorType) args.intMethod);
+    if (ret != 0)
+    {
+        printf("Set ret = %d\n", ret);
+        delete inter;
+        return ret;
+    }
+
+    // read frame into buffer / create destination buffer
+    if ((outputFile = fopen(outname.c_str(), "wb")) == NULL)
+    {
+        printf("Cannot write file %s.\n", outname.c_str());
+
+        exit(1);
+    }
+
+    std::string inname = args.inputFile;
+    if ((sourceFile = fopen(inname.c_str(), "rb")) == NULL)
+    {
+        printf("Cannot read file %s.\n", inname.c_str());
+        exit(1);
+    }
+
+    WebRtc_UWord32 inRequiredSize = args.width * args.height * 3 >> 1;
+    WebRtc_UWord32 outRequiredSize = args.dstWidth * args.dstHeight * 3 >> 1;
+    WebRtc_UWord8* inputBuffer = new WebRtc_UWord8[inRequiredSize];
+    WebRtc_UWord8* outputBuffer = NULL;
+
+    //
+    clock_t startClock, TotalClock;
+    TotalClock = 0;
+    //
+    // running through entire sequence
+    int frameCnt = 0;
+    while (feof(sourceFile)== 0)
+    {
+        if (inRequiredSize != fread(inputBuffer, 1, inRequiredSize, sourceFile))
+            break;
+
+        startClock = clock();
+        ret = inter->Interpolate(inputBuffer, outputBuffer);
+        TotalClock += clock() - startClock;
+
+        if (ret == args.dstHeight)
+        {
+            fwrite(outputBuffer, 1, outRequiredSize, outputFile);
+            ret = 0;  // signaling OK to main tester
+        }
+        else
+        {
+            printf("frame #%d: Interpolation Error, ret = %d\n", frameCnt, ret);
+        }
+
+        if (outputBuffer)
+        {
+            delete [] outputBuffer;
+            outputBuffer = NULL;
+        }
+        frameCnt++;
+        printf(".");
+    }
+
+    printf("\nProcessed %d frames\n", frameCnt);
+    if (frameCnt)
+        printf("\nAvg. Time per frame[mS]: %.2lf\n",
+              (1000.0 * static_cast<double>(TotalClock + 0.0)
+               /CLOCKS_PER_SEC)/frameCnt);
+
+    if (outputBuffer)
+        delete [] outputBuffer;
+
+    fclose(sourceFile);
+    fclose(outputFile);
+
+
+    // wrap up
+    delete inter;
+    delete [] inputBuffer;
+
+    return ret;
+}
diff --git a/common_video/vplib/main/test/scale_test.cc b/common_video/vplib/main/test/scale_test.cc
new file mode 100644
index 0000000..611060d
--- /dev/null
+++ b/common_video/vplib/main/test/scale_test.cc
@@ -0,0 +1,695 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <cassert>
+#include <iostream>
+#include <string>
+
+#include "vplib.h"
+
+#include <cstring>
+
+using namespace webrtc;
+
+#define TEST_STR "Test Scale."
+#define TEST_PASSED() std::cerr << TEST_STR << " : [OK]" << std::endl
+#define PRINT_LINE std::cout << "------------------------------------------" << std::endl;
+
+void PrintFrame(WebRtc_UWord8* ptrFrame, WebRtc_Word32 width, WebRtc_Word32 height)
+{
+    WebRtc_Word32 k = 0;
+    for (WebRtc_Word32 i = 0; i < height; i++)
+    {
+        for (WebRtc_Word32 j = 0; j < width; j++)
+        {
+            std::cout << (WebRtc_Word32)ptrFrame[k++] << " ";
+        }
+        std::cout << " " << std::endl;
+    }
+    std::cout << " " << std::endl;
+}
+
+
+void PrintFrame(WebRtc_UWord8* ptrInFrame, WebRtc_Word32 width, WebRtc_Word32 height, const WebRtc_Word8* str)
+{
+    std::cout << str << " (" << width << "x" << height << ") = " << std::endl;
+
+    WebRtc_UWord8* ptrFrameY  = ptrInFrame;
+    WebRtc_UWord8* ptrFrameCb = ptrFrameY  + width*height;
+    WebRtc_UWord8* ptrFrameCr = ptrFrameCb + width*height/4;
+   
+    PrintFrame(ptrFrameY,  width,   height);
+    PrintFrame(ptrFrameCb, width/2, height/2);
+    PrintFrame(ptrFrameCr, width/2, height/2);  
+}
+
+void CreateImage(WebRtc_Word32 width, WebRtc_Word32 height, WebRtc_UWord8* ptrFrame, WebRtc_Word32 offset, WebRtc_Word32 heightFactor, WebRtc_Word32 widthFactor = 0)
+{
+    for (WebRtc_Word32 i = 0; i < height; i++)
+    {
+        for (WebRtc_Word32 j = 0; j < width; j++)
+        {
+            *ptrFrame = (WebRtc_UWord8)((i + offset)*heightFactor + j*widthFactor);
+            ptrFrame++;
+        }
+    }
+}
+
+void ValidateImage2(WebRtc_Word32 width, WebRtc_Word32 height, WebRtc_UWord8* ptrFrame, WebRtc_Word32 offset, WebRtc_Word32 factor)
+{
+    WebRtc_Word32 k = 0;
+    WebRtc_Word32 res = offset*factor;
+    for (WebRtc_Word32 i = 0; i < height; i++)
+    {
+        for (WebRtc_Word32 j = 0; j < width; j++)
+        {
+            assert(ptrFrame[k++] == res);
+        }
+        if (i > 0)
+        {
+            res += factor/2;
+        }
+    }
+}
+
+void ValidateImage3_2(WebRtc_Word32 width, WebRtc_Word32 height, WebRtc_UWord8* ptrFrame, WebRtc_Word32 offset, WebRtc_Word32 factor)
+{
+    WebRtc_Word32 k = 0;
+    bool inc = true;
+    WebRtc_Word32 res = offset*factor;
+    for (WebRtc_Word32 i = 1; i <= height; i++)
+    {
+        for (WebRtc_Word32 j = 0; j < width; j++)
+        {
+            assert(ptrFrame[k++] == res);
+        }
+        res += factor/2;
+        if ((i % 3) == 0)
+        {
+            res += factor/2;  
+        }
+    }
+}
+
+void ValidateImage1_3(WebRtc_Word32 width, WebRtc_Word32 height, WebRtc_UWord8* ptrFrame, WebRtc_Word32 offset, WebRtc_Word32 factor)
+{
+    WebRtc_Word32 k = 0;
+    WebRtc_Word32 res = offset*factor;
+    res += factor/2;
+    for (WebRtc_Word32 i = 0; i < height; i++)
+    {
+        for (WebRtc_Word32 j = 0; j < width; j++)
+        {
+            assert(ptrFrame[k++] == res);
+        }
+        res += factor*3;  
+    }
+}
+
+static void VerifyInBounds(const WebRtc_UWord8* ptrImage, const WebRtc_Word32 imageLength, 
+                           const WebRtc_Word32 startOffset, const WebRtc_Word32 endOffset)
+{
+    // Verify that function does not write outside buffer
+    const WebRtc_UWord8* ptrFrameStart = ptrImage - startOffset;
+    const WebRtc_UWord8* ptrFrameEnd   = ptrImage + imageLength;
+
+    // Verify that function does not write outside buffer
+    for (WebRtc_Word32 i = 0; i < startOffset; i++)
+    {
+        assert(ptrFrameStart[i] == 255);
+    }
+
+    for (WebRtc_Word32 i = 0; i < endOffset; i++)
+    {
+        assert(ptrFrameEnd[i] == 255);
+    }
+}
+
+WebRtc_Word32 
+VerifyAndAllocateTest(WebRtc_UWord8*& buffer, WebRtc_Word32 currentSize, WebRtc_Word32 newSize)
+{
+    if(newSize > currentSize)
+    {
+        // make sure that our buffer is big enough
+        WebRtc_UWord8* newBuffer = new WebRtc_UWord8[newSize];
+        if(buffer)
+        {
+            // copy the old data
+            memcpy(newBuffer, buffer, currentSize);
+            delete [] buffer;
+        }
+        buffer = newBuffer;
+        return newSize;
+    }
+
+    return currentSize;
+}
+
+//--------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------
+
+int
+scale_test()
+{
+
+  std::string str;
+    std::cout << "--------------------------------" << std::endl;
+    std::cout << "-------- Test Scaling ----------" << std::endl;
+    std::cout << "--------------------------------" << std::endl;
+    std::cout << "  "  << std::endl;
+  
+    // -------------------------------
+    // Test ScaleI420Up2() -----------
+    // -------------------------------
+    PRINT_LINE;
+    std::cout << "Test ScaleI420Up2()" << std::endl;
+    PRINT_LINE;
+
+    WebRtc_UWord32 width = 12;
+    WebRtc_UWord32 height = 10;
+    WebRtc_Word32 factorY = 2;
+    WebRtc_Word32 factorCb = 10;
+    WebRtc_Word32 factorCr = 20;
+    WebRtc_Word32 offset = 5;
+    WebRtc_Word32 startBufferOffset = 10;
+    WebRtc_UWord32 length = CalcBufferSize(kI420, width, height);
+
+    // Test bad inputs
+    WebRtc_UWord32 scW = 0;
+    WebRtc_UWord32 scH = 0;
+   
+    WebRtc_UWord8* testFrame = new WebRtc_UWord8[length + offset];
+    WebRtc_Word32 retVal = ScaleI420Up2(0, height,testFrame,length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(width, 0, testFrame,length,  scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(49, height, testFrame, length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(width, 3, testFrame,length, scW, scH);   // odd height
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(width + 2, height, testFrame,length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(width, height + 2, testFrame,length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Up2(width, height, testFrame,length, scW, scH);     // width, height == allocated buffer size, OK
+    assert(retVal == scW * scH * 3 / 2);
+    delete [] testFrame;
+
+    testFrame = new WebRtc_UWord8[  length * 4 + startBufferOffset * 2];
+    memset(testFrame, 255, length * 4 + startBufferOffset * 2);
+
+    // Create input frame
+    WebRtc_UWord8* ptrFrameY = testFrame;
+    WebRtc_UWord8* ptrFrameCb = ptrFrameY + width*height;
+    WebRtc_UWord8* ptrFrameCr = ptrFrameCb + width*height/4;
+    CreateImage(width,   height,   ptrFrameY,  offset, factorY);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, offset, factorCb); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, offset, factorCr); // Cr
+    PrintFrame(testFrame, width, height, "InputFrame");
+
+    // Scale frame to twice its size
+    WebRtc_UWord32 scaledWidth = 0;
+    WebRtc_UWord32 scaledHeight = 0;
+    retVal = ScaleI420Up2(width, height, testFrame, length * 4 + startBufferOffset * 2, scaledWidth, scaledHeight);
+   
+    PrintFrame(testFrame, scaledWidth, scaledHeight, "Output Frame");
+
+    // Validate results
+    assert(retVal == scaledWidth * scaledHeight * 3 / 2);
+    ptrFrameY = testFrame;
+    ptrFrameCb  = ptrFrameY  + scaledWidth*scaledHeight;
+    ptrFrameCr  = ptrFrameCb + scaledWidth*scaledHeight/4;
+
+    ValidateImage2(scaledWidth,   scaledHeight,   ptrFrameY,  offset, factorY);
+    ValidateImage2(scaledWidth/2, scaledHeight/2, ptrFrameCb, offset, factorCb);
+    ValidateImage2(scaledWidth/2, scaledHeight/2, ptrFrameCr, offset, factorCr);
+
+    delete [] testFrame;
+
+    // --------------------------------
+    // Test ScaleI420Up3_2() ----------
+    // --------------------------------
+    PRINT_LINE;
+    std::cout << "Test ScaleI420Up3_2()" << std::endl;
+    PRINT_LINE;
+
+    width = 12;
+    height = 8;
+    factorY = 2;
+    factorCb = 10;
+    factorCr = 20;
+    offset = 5;
+    startBufferOffset = 10;
+    length = CalcBufferSize(kI420, width, height);
+
+    // Test bad inputs
+    testFrame = new WebRtc_UWord8[length];
+
+    retVal = ScaleI420Up3_2(0, height, testFrame,length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width, 0, testFrame,length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(49, height, testFrame,length, scW, scH); // odd width
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width, 3, testFrame,length, scW, scH);   // odd height
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width, 10, testFrame,length, scW, scH);   // odd height (color)
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(14, height, testFrame,length, scW, scH);   // odd width (color)
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width + 2, height, testFrame,length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width, height + 2, testFrame,length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Up3_2(width, height, testFrame,length, scW, scH);     // width, height == allocated buffer size, OK
+    assert(retVal == scW * scH * 3 / 2);
+
+    delete [] testFrame;
+       
+    testFrame = new WebRtc_UWord8[length + startBufferOffset];
+    memset(testFrame, 255, length + startBufferOffset);
+    
+    // Create input frame
+    ptrFrameY = testFrame;
+    ptrFrameCb = ptrFrameY + width*height;
+    ptrFrameCr = ptrFrameCb + width*height/4;
+    CreateImage(width,   height,   ptrFrameY,  offset, factorY);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, offset, factorCb); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, offset, factorCr); // Cr
+    PrintFrame(testFrame, width, height, "Input Frame");
+
+
+    // Scale frame to 1.5 times its size
+    scaledWidth = 0;
+    scaledHeight = 0;
+    retVal = ScaleI420Up3_2(width, height, testFrame, length + startBufferOffset, scaledWidth, scaledHeight);
+    
+    PrintFrame(testFrame, scaledWidth, scaledHeight, "Output Frame");
+
+    // Validate results
+    assert(retVal == scaledWidth * scaledHeight * 3 / 2);
+
+    // Verify that function does not write outside buffer
+    ptrFrameY  = testFrame;//imageBuffer.GetBuffer();
+    ptrFrameCb = ptrFrameY  + scaledWidth*scaledHeight;
+    ptrFrameCr = ptrFrameCb + scaledWidth*scaledHeight/4;
+
+    ValidateImage3_2(scaledWidth,   scaledHeight,   ptrFrameY,  offset, factorY);
+    ValidateImage3_2(scaledWidth/2, scaledHeight/2, ptrFrameCb, offset, factorCb);
+    ValidateImage3_2(scaledWidth/2, scaledHeight/2, ptrFrameCr, offset, factorCr);
+
+    delete [] testFrame;
+
+    // --------------------------------
+    // Test ScaleI420Down1_3() ----------
+    // --------------------------------
+    PRINT_LINE;
+    std::cout << "Test ScaleI420Up1_3()" << std::endl;
+    PRINT_LINE;
+
+    width = 10;
+    height = 8;
+    factorY = 2;
+    factorCb = 10;
+    factorCr = 20;
+    offset = 5;
+    startBufferOffset = 10;
+    length = webrtc::CalcBufferSize(kI420, width, height);
+
+    // Test bad inputs
+    testFrame = new WebRtc_UWord8[length];
+    retVal = ScaleI420Down1_3(0, height, testFrame, length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(width, 0, testFrame, length, scW, scH);
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(49, height, testFrame, length, scW, scH); // odd width
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(width, 3, testFrame, length, scW, scH);   // odd height
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(width + 2, height, testFrame, length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(width, height + 2, testFrame, length, scW, scH); // width, height > allocated buffer size
+    assert(retVal == -1);
+    retVal = ScaleI420Down1_3(width, height, testFrame, length, scW, scH);     // width, height == allocated buffer size, ok
+    assert(retVal == scW * scH * 3 / 2);
+    
+    delete [] testFrame;
+        
+    testFrame = new WebRtc_UWord8[length + startBufferOffset * 2];
+    memset(testFrame, 255, length + startBufferOffset * 2);
+    // Create input frame
+    ptrFrameY = testFrame;
+    ptrFrameCb = ptrFrameY + width*height;
+    ptrFrameCr = ptrFrameCb + width*height/4;
+    CreateImage(width,   height,   ptrFrameY,  offset, factorY);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, offset, factorCb); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, offset, factorCr); // Cr
+    PrintFrame(testFrame, width, height, "Input Frame");
+
+    // Scale frame to one third its size
+    scaledWidth = 0;
+    scaledHeight = 0;
+    retVal = ScaleI420Down1_3(width, height, testFrame, length + startBufferOffset * 2 , scaledWidth, scaledHeight);
+    
+    PrintFrame(testFrame, scaledWidth, scaledHeight, "Output Frame");
+
+    // Validate results
+    assert(retVal == scaledWidth * scaledHeight * 3 / 2);
+
+    // Verify that function does not write outside buffer
+    ptrFrameY  = testFrame;//imageBuffer.GetBuffer();
+    ptrFrameCb = ptrFrameY  + scaledWidth*scaledHeight;
+    ptrFrameCr = ptrFrameCb + scaledWidth*scaledHeight/4;
+
+    ValidateImage1_3(scaledWidth,   scaledHeight,   ptrFrameY,  offset, factorY);
+    ValidateImage1_3(scaledWidth/2, scaledHeight/2, ptrFrameCb, offset, factorCb);
+    ValidateImage1_3(scaledWidth/2, scaledHeight/2, ptrFrameCr, offset, factorCr);
+
+    delete [] testFrame;
+
+    // -------------------
+    // Test PadI420Frame()
+    // -------------------
+    PRINT_LINE;
+    std::cout << "Test PadI420Frame()" << std::endl;
+    PRINT_LINE;
+
+    width = 16;
+    height = 8;
+    factorY = 1;
+    factorCb = 1;
+    factorCr = 1;
+    offset = 5;
+    startBufferOffset = 10;
+    length = CalcBufferSize(kI420, width, height);
+
+    testFrame = new WebRtc_UWord8[length];
+    memset(testFrame, 255, length);
+
+    // Create input frame
+    ptrFrameY = testFrame;//imageBuffer.GetBuffer();
+    ptrFrameCb = ptrFrameY + width*height;
+    ptrFrameCr = ptrFrameCb + width*height/4;
+    CreateImage(width,   height,   ptrFrameY,  1, factorY);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, 100, factorCb); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, 200, factorCr); // Cr
+    PrintFrame(testFrame, width, height, "Input Frame");
+
+    WebRtc_UWord8* testFrame2 = new WebRtc_UWord8[352*288];
+
+    // Test bad input
+    assert(PadI420Frame(NULL, testFrame2, 16, 16, 32, 32) == -1);
+    assert(PadI420Frame(testFrame, NULL, 16, 16, 32, 32) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 0, 16, 32, 32) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 0, 32, 32) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 16, 0, 32) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 16, 32, 0) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 16, 8, 32) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 16, 32, 8) == -1);
+    assert(PadI420Frame(testFrame, testFrame2, 16, 16, 16, 16) == 3 * 16 * 16 / 2);
+
+    enum { NumOfPaddedSizes = 4 };
+    WebRtc_Word32 paddedWidth[NumOfPaddedSizes] = { 32, 22, 16, 20 };
+    WebRtc_Word32 paddedHeight[NumOfPaddedSizes] = { 16, 14, 12, 8 };
+    
+    for (WebRtc_Word32 i = 0; i < NumOfPaddedSizes; i++)
+    {
+        scaledWidth = paddedWidth[i];
+        scaledHeight = paddedHeight[i];
+        
+        WebRtc_Word32 toLength = webrtc::CalcBufferSize(kI420, scaledWidth, scaledHeight);
+
+         if (testFrame2)
+         {
+             delete [] testFrame2;
+         }
+         testFrame2 = new WebRtc_UWord8[toLength + startBufferOffset * 2];
+         memset(testFrame2, 255, toLength + startBufferOffset * 2);
+
+
+        retVal = webrtc::PadI420Frame(testFrame, testFrame2, width, height, scaledWidth, scaledHeight);
+        PrintFrame(testFrame2, scaledWidth, scaledHeight, "Output Frame");
+        
+        // Validate results
+        assert(retVal == toLength);
+
+    }
+    std::cout << "Do the padded frames look correct?" << std::endl
+        << "(Padded dimensions which are multiples of 16 will have the" << std::endl
+        << "padding applied in blocks of 16)" << std::endl
+        << "Press enter to continue...";
+    std::getline(std::cin, str);
+
+    // -----------------
+    // Test video sizes
+    // -----------------
+    const WebRtc_Word32 nr = 16;
+    // currently not keeping video sizes as a type - testing scaling functions only
+    WebRtc_UWord16 widths[nr] =  {128, 160, 176, 320, 352, 640, 720, 704, 800, 960, 1024, 1440, 400, 800, 1280, 1920};
+    WebRtc_UWord16 heights[nr] = { 96, 120, 144, 240, 288, 480, 480, 576, 600, 720,  768, 1080, 240, 480,  720, 1080};
+
+    for (WebRtc_Word32 j = 0; j < 3; j++)
+    {
+        for (WebRtc_Word32 i = 0; i < nr; i++)
+        {
+            width = widths[i];
+            height = heights[i];
+            factorY = 2;
+            factorCb = 2;
+            factorCr = 2;
+            offset = 2;
+            startBufferOffset = 10;
+            length = webrtc::CalcBufferSize(kI420, width, height);
+
+            float f = 1;
+            if (j == 0)
+            {
+                f = 2;
+            }
+            else if (j == 1)
+            {
+                f = 1.5;
+            }
+            else if (j == 2)
+            {
+                f = 1;
+            }
+
+            if (testFrame)
+            {
+                delete testFrame;
+                testFrame = 0;
+            }
+            WebRtc_Word32 frameSize = (WebRtc_Word32) ((length * f * f) + startBufferOffset * 2);
+            testFrame = new WebRtc_UWord8[frameSize];
+            memset(testFrame, 255, frameSize);
+          
+            // Create input frame
+            ptrFrameY = testFrame;
+            ptrFrameCb = ptrFrameY + width*height;
+            ptrFrameCr = ptrFrameCb + width*height/4;
+            CreateImage(width,   height,   ptrFrameY,  offset, factorY);  // Y
+            CreateImage(width/2, height/2, ptrFrameCb, offset, factorCb); // Cb
+            CreateImage(width/2, height/2, ptrFrameCr, offset, factorCr); // Cr
+          
+            scaledWidth = 0;
+            scaledHeight = 0;
+            if (j == 0)
+            {
+                retVal = ScaleI420Up2(width, height, testFrame,frameSize, scaledWidth, scaledHeight);
+                length = scaledWidth*scaledHeight*3/2;
+            }
+            else if (j == 1)
+            {
+                retVal = ScaleI420Up3_2(width, height, testFrame,frameSize, scaledWidth, scaledHeight);
+                length = scaledWidth*scaledHeight*3/2;
+            }
+            else if (j == 2)
+            {
+                retVal = ScaleI420Down1_3(width, height, testFrame,frameSize, scaledWidth, scaledHeight);
+                length = width*height*3/2;
+            }
+
+            // Validate results
+            assert(retVal == scaledWidth * scaledHeight * 3 / 2);
+        }
+    }
+
+    // ---------------------
+    // Test mirror functions
+    // ---------------------
+    std::cout << "Test Mirror function" << std::endl;
+    
+    // 4:2:0 images can't have odd width or height
+    width = 16;
+    height = 8;
+    factorY = 1;
+    factorCb = 1;
+    factorCr = 1;
+    offset = 5;
+    startBufferOffset = 10;
+    length = webrtc::CalcBufferSize(kI420, width, height);
+
+    delete [] testFrame;
+    testFrame = new WebRtc_UWord8[length];
+    memset(testFrame, 255, length);
+
+    // Create input frame
+    WebRtc_UWord8* inFrame = testFrame;
+    ptrFrameCb = inFrame + width * height;
+    ptrFrameCr = ptrFrameCb + (width * height) / 4;
+    CreateImage(width,   height,   inFrame,  10, factorY, 1);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, 100, factorCb, 1); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, 200, factorCr, 1); // Cr
+    PrintFrame(testFrame, width, height, "Input Frame");
+
+    if (testFrame2)
+    {
+        delete [] testFrame2;
+        testFrame2 = 0;
+    }
+    testFrame2 = new WebRtc_UWord8[length + startBufferOffset * 2];
+    memset(testFrame2, 255, length + startBufferOffset * 2);
+    WebRtc_UWord8* outFrame = testFrame2;
+    
+    // LeftRight
+    std::cout << "Test Mirror function: LeftRight" << std::endl;
+    retVal = MirrorI420LeftRight(inFrame, outFrame, width, height);
+    PrintFrame(testFrame2, width, height, "Output Frame");
+    retVal = MirrorI420LeftRight(outFrame, outFrame, width, height);
+
+    assert(memcmp(inFrame, outFrame, length) == 0);
+    //VerifyInBounds(outFrame, length, startBufferOffset, startBufferOffset);
+    
+    //UpDown
+    std::cout << "Test Mirror function: UpDown" << std::endl;
+    retVal = MirrorI420UpDown(inFrame, outFrame, width, height);
+    PrintFrame(testFrame2, width, height, "Output Frame");
+    retVal = MirrorI420UpDown(outFrame, outFrame, width, height);
+
+    assert(memcmp(inFrame, outFrame, length) == 0);
+    //VerifyInBounds(outFrame, length, startBufferOffset, startBufferOffset);
+
+    std::cout << "Do the mirrored frames look correct?" << std::endl
+        << "Press enter to continue...";
+    std::getline(std::cin, str);
+  // end Mirror Function check
+
+    delete [] testFrame;
+    testFrame = new WebRtc_UWord8[length];
+    memset(testFrame,255,length);
+    inFrame = testFrame;
+
+    CreateImage(width,   height,   inFrame,  10, factorY, 1);  // Y
+    CreateImage(width/2, height/2, ptrFrameCb, 100, factorCb, 1); // Cb
+    CreateImage(width/2, height/2, ptrFrameCr, 200, factorCr, 1); // Cr
+
+    PrintFrame(inFrame, width, height, "Input frame");
+
+    delete [] testFrame2;
+    testFrame2 = new WebRtc_UWord8[length];
+    memset(testFrame2, 255, length);
+    int yv12Size = CalcBufferSize(kI420, kYV12, length);
+    WebRtc_UWord8* yv12TestFrame = new WebRtc_UWord8[yv12Size];
+    memset(yv12TestFrame, 255, yv12Size);
+    outFrame = testFrame2;    
+    retVal = ConvertI420ToYV12(inFrame, yv12TestFrame, width, height, 0);
+    assert(retVal >= 0);
+
+    // Test convert and mirror functions
+    ConvertToI420AndMirrorUpDown(yv12TestFrame, outFrame, width, height, kYV12);
+    std::cout << "Test: ConvertAndMirrorUpDown" << std::endl;
+    PrintFrame(outFrame, width, height, "Output Frame");
+    MirrorI420UpDown(outFrame, outFrame, width, height);
+    assert(memcmp(inFrame, outFrame, length) == 0);
+    std::cout << "Does the converted (U and V flipped) mirrored frame look correct?" << std::endl
+        << "Press enter to continue...";
+    std::getline(std::cin, str);
+    delete [] testFrame2;
+
+    PrintFrame(inFrame, width, height, "Input frame");
+
+    // Test convert and rotate functions
+    testFrame2 = new WebRtc_UWord8[length];
+    memset(testFrame2, 255, length);
+    outFrame = testFrame2;
+    WebRtc_UWord8* tempFrame = new WebRtc_UWord8[length];
+
+    ConvertToI420(kYV12, yv12TestFrame, width, height, outFrame, false, kRotateAntiClockwise);
+    std::cout << "Test: ConvertAndRotateAntiClockwise" << std::endl;
+    PrintFrame(outFrame, height, width, "Output Frame");
+    ConvertToI420(kI420, outFrame, height, width, tempFrame, false, kRotateAntiClockwise);
+    ConvertToI420(kI420, tempFrame, width, height, outFrame, false, kRotateAntiClockwise);
+    ConvertToI420(kI420, outFrame, height, width, tempFrame, false, kRotateAntiClockwise);
+    assert(memcmp(inFrame, tempFrame, length) == 0);
+
+    delete [] testFrame2;
+
+    testFrame2 = new WebRtc_UWord8[length];
+    outFrame = testFrame2;
+    memset(outFrame, 255, length);
+    memset(tempFrame, 255, length);
+    ConvertToI420(kYV12, yv12TestFrame, width, height, outFrame, false, kRotateClockwise);
+    std::cout << "Test: ConvertAndRotateClockwise" << std::endl;
+    PrintFrame(outFrame, height, width, "Output Frame");
+    ConvertToI420(kI420, outFrame, height, width, tempFrame, false, kRotateClockwise);
+    ConvertToI420(kI420, tempFrame, width, height, outFrame, false, kRotateClockwise);
+    ConvertToI420(kI420, outFrame, height, width, tempFrame, false, kRotateClockwise);
+    assert(memcmp(inFrame, tempFrame, length) == 0);
+
+    delete [] testFrame2;
+
+    std::cout << "Do the converted (U and V flipped) and rotated frames look correct?" << std::endl
+        << "Press enter to continue...";
+    std::getline(std::cin, str);
+
+
+    PrintFrame(inFrame, width, height, "Input frame");
+
+    // Test rotation with padding
+   
+    height += 4;
+    length = width * height * 3 / 2;
+    testFrame2 = new WebRtc_UWord8[length];
+    memset(testFrame2, 255, length);
+    outFrame = testFrame2;
+    webrtc::ConvertToI420(kYV12, yv12TestFrame, width, height - 4, outFrame, false, webrtc::kRotateClockwise);
+    std::cout << "Test: ConvertAndRotateClockwise (width padding)" << std::endl;
+    PrintFrame(outFrame, height, width, "Output Frame");
+
+    width += 4;
+    height -= 4;
+    memset(testFrame2, 255, length);
+    outFrame = testFrame2;
+    ConvertToI420(kYV12, yv12TestFrame, width - 4, height, outFrame, false, webrtc::kRotateAntiClockwise);
+    std::cout << "Test: ConvertAndRotateClockwise (height padding)" << std::endl;
+    PrintFrame(outFrame, height, width, "Output Frame");
+
+    std::cout << "Do the rotated and padded images look correct?" << std::endl
+        << "Press enter to continue...";
+    std::getline(std::cin, str);
+
+    delete [] tempFrame;
+    tempFrame = NULL;
+    delete [] testFrame;
+    testFrame = NULL;
+    delete [] testFrame2;
+    testFrame2 = NULL;
+    delete [] yv12TestFrame;
+    yv12TestFrame = NULL;
+
+    TEST_PASSED();
+    std::cout << "Press enter to quit test...";
+    std::getline(std::cin, str);
+
+    return 0;
+}
diff --git a/common_video/vplib/main/test/test_util.h b/common_video/vplib/main/test/test_util.h
new file mode 100644
index 0000000..7fd34da
--- /dev/null
+++ b/common_video/vplib/main/test/test_util.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef COMMON_VIDEO_VPLIB_TEST_UTIL_H
+#define COMMON_VIDEO_VPLIB_TEST_UTIL_H
+
+#include <string.h>
+#include <fstream>
+#include <cstdlib>
+
+
+class CmdArgs
+{
+public:
+    CmdArgs() : width(-1), height(-1), dstWidth(-1), dstHeight(-1),
+                intMethod(-1), inputFile(""), outputFile(""), testNum(-1)
+    {}
+    int width;
+    int height;
+    int dstWidth;
+    int dstHeight;
+    int intMethod;
+    std::string inputFile;
+    std::string outputFile;
+    int testNum;
+};
+
+int interpolationTest(CmdArgs& args);
+int convert_test(CmdArgs& args);
+int scale_test();
+
+#endif  // COMMON_VIDEO_VPLIB_TEST_UTIL_H
diff --git a/common_video/vplib/main/test/tester_main.cc b/common_video/vplib/main/test/tester_main.cc
new file mode 100644
index 0000000..090a56c
--- /dev/null
+++ b/common_video/vplib/main/test/tester_main.cc
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vplib.h"
+#include "test_util.h"
+
+using namespace webrtc;
+
+int ParseArguments(int argc, char **argv, CmdArgs& args)
+{
+    int i = 1;
+    while (i < argc)
+    {
+        if (argv[i][0] != '-')
+        {
+            return -1;
+        }
+        switch (argv[i][1])
+        {
+        case 'w':
+        {
+            int w = atoi(argv[i+1]);
+            if (w < 1)
+                return -1;
+            args.width = w;
+            break;
+        }
+        case 'h':
+        {
+            int h = atoi(argv[i+1]);
+            if (h < 1)
+                return -1;
+            args.height = h;
+            break;
+        }
+        case 'x':
+        {
+            int x = atoi(argv[i+1]);
+            if (x < 1)
+                return -1;
+            args.dstWidth = x;
+            break;
+        }
+        case 'y':
+        {
+            int y = atoi(argv[i+1]);
+            if (y < 1)
+                return -1;
+            args.dstHeight = y;
+            break;
+        }
+        case 'm': // interpolation method
+        {
+            int m = atoi(argv[i+1]);
+            if (m < 0)
+                return -1;
+            args.intMethod = m;
+            break;
+        }
+        case 'i':
+        {
+            args.inputFile = argv[i+1];
+            break;
+        }
+        case 'o':
+            args.outputFile = argv[i+1];
+            break;
+        case 'n':
+        {
+            int n = atoi(argv[i+1]);
+            if (n < 1)
+                return -1;
+            args.testNum = n;
+            break;
+        }
+        default:
+            return -1;
+        }
+        i += 2;
+    }
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    CmdArgs args;
+
+    if (ParseArguments(argc, argv, args) != 0)
+    {
+        printf("Unable to parse input arguments\n");
+        printf("args: -n <test #> -w <width> -h <height>  "
+               "-x <destination width> -y <destination height> -f <fps> "
+               "-b <bps> -m <method> -i <input file> -o <output file>\n");
+        return -1;
+    }
+    int ret = -1;
+    switch (args.testNum)
+    {
+        printf("\n");
+        case 1:
+            printf("VPLIB Interpolation Test\n");
+            ret = interpolationTest(args);
+            break;
+        case 2:
+            printf("VPLIB Scale Test\n");
+            ret = scale_test();
+            break;
+        case 3:
+            printf("VPLIB Convert Test\n");
+            ret = convert_test(args);
+            break;
+        default:
+            ret = -1;
+            break;
+    }
+    if (ret != 0)
+    {
+        printf("Test failed!\n");
+        return -1;
+    }
+    return 0;
+}